/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 package org.mangui.chromeless {
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.event.HLSLoadMetrics;
    import org.mangui.hls.event.HLSPlayMetrics;
    import org.mangui.hls.HLS;
    import org.mangui.hls.stream.HLSNetStream;
    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    /*
     * class that handle per playback session stats
     */
     public class StatsHandler {
        /** Reference to the HLS controller. **/
        private var _hls : HLS;
        private var _stats : Object;
        private var _sumLatency : int;
        private var _sumKbps : int;
        private var _sumAutoLevel : int;
        private var _levelLastAuto : Boolean;

        public function StatsHandler(hls : HLS) {
            _hls = hls;
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_PLAYING,_fragmentPlayingHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_SKIPPED,_fragmentSkippedHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_LOAD_EMERGENCY_ABORTED,_fragmentLoadEmergencyAbortedHandler);
            _hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
        }

        public function dispose() : void {
            _hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.removeEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
            _hls.removeEventListener(HLSEvent.FRAGMENT_PLAYING, _fragmentPlayingHandler);
            _hls.removeEventListener(HLSEvent.FRAGMENT_SKIPPED,_fragmentSkippedHandler);
            _hls.removeEventListener(HLSEvent.FRAGMENT_LOAD_EMERGENCY_ABORTED,_fragmentLoadEmergencyAbortedHandler);
            _hls.removeEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
        }

        public function get stats() : Object {
            return _stats;
        }

        private function _manifestLoadedHandler(event : HLSEvent) : void {
            _stats = {};
        };

        private function _fragmentLoadedHandler(event : HLSEvent) : void {
            var metrics : HLSLoadMetrics = event.loadMetrics;
            var latency : int = metrics.loading_begin_time-metrics.loading_request_time;
            var bandwidth : int = metrics.bandwidth/1000;
            if(_stats.fragBuffered) {
              _stats.fragLastLatency = latency;
              _stats.fragMinLatency = Math.min(_stats.fragMinLatency,latency);
              _stats.fragMaxLatency = Math.max(_stats.fragMaxLatency,latency);
              _stats.fragLastKbps = bandwidth;
              _stats.fragMinKbps = Math.min(_stats.fragMinKbps,bandwidth);
              _stats.fragMaxKbps = Math.max(_stats.fragMaxKbps,bandwidth);
              _stats.fragBuffered++;
            } else {
                  _stats.fragMinLatency = _stats.fragMaxLatency = latency;
                  _stats.fragMinKbps = _stats.fragMaxKbps = bandwidth;
                  _stats.fragBuffered = 1;
                  _stats.fragBufferedBytes = 0;
                  _sumLatency=0;
                  _sumKbps=0;
            }
            _sumLatency+=latency;
            _sumKbps+=bandwidth;
            _stats.fragBufferedBytes+=metrics.size;
            _stats.fragAvgLatency = Math.round(_sumLatency/_stats.fragBuffered);
            _stats.fragAvgKbps = Math.round(_sumKbps/_stats.fragBuffered);
        }

        private function _fragmentPlayingHandler(event : HLSEvent) : void {
        if(_stats.fragPlaying) {
            _stats.fragPlaying++;
        } else {
            _stats.fragPlaying = 1;
        }
      }

      private function _fragmentSkippedHandler(event : HLSEvent) : void {
        if(_stats.fragSkipped) {
            _stats.fragSkipped++;
        } else {
            _stats.fragSkipped = 1;
        }
      }

      private function _fragmentLoadEmergencyAbortedHandler(event : HLSEvent) : void {
        if(_stats.fragLoadEmergencyAborted) {
            _stats.fragLoadEmergencyAborted++;
        } else {
            _stats.fragLoadEmergencyAborted = 1;
        }
      }

      private function _mediaTimeHandler(event : HLSEvent) : void {
        _stats.droppedFrames = _hls.droppedFrames;
      }
  }
}
