$ = jQuery
context = window
logger = context.JK.logger
rest = context.JK.Rest()
EVENTS = context.JK.EVENTS
MIX_MODES = context.JK.MIX_MODES

SessionActions = @SessionActions
MixerActions = @MixerActions

SessionStatThresholds = gon.session_stat_thresholds
NetworkThresholds = SessionStatThresholds.network
SystemThresholds = SessionStatThresholds.system
AudioThresholds = SessionStatThresholds.audio
AggregateThresholds = SessionStatThresholds.aggregate

@SessionStatsStore = Reflux.createStore(
  {
    listenables: @SessionStatsActions
    rawStats: null,
    parentStats: null
    clientsWithAudio: null

    init: ->
      # Register with the app store to get @app
      this.listenTo(context.AppStore, this.onAppInit)

    onAppInit: (@app) ->

    onPushStats: (stats, parentStats) ->
      @rawStats = stats
      @parentStats = parentStats
      @changed()

    classify: (holder, field, threshold) ->
      value = holder[field]
      fieldLevel = field + '_level'
      fieldThreshold = threshold[field]

      if value? && fieldThreshold?

        if fieldThreshold.inverse
          if fieldThreshold.zero_is_good
            holder[fieldLevel] = 'good'
          else if value <= fieldThreshold.poor
            holder[fieldLevel] = 'poor'
            @participantClassification = 3
          else if value <= fieldThreshold.warn
            holder[fieldLevel] = 'warn'
            @participantClassification = 2 if @participantClassification == 1
          else
            holder[fieldLevel] = 'good'
        else if fieldThreshold.eql
          if value == fieldThreshold.poor
            holder[fieldLevel] = 'poor'
            @participantClassification = 3
          else if value == fieldThreshold.warn
            holder[fieldLevel] = 'warn'
            @participantClassification = 2 if @participantClassification == 1
          else
            holder[fieldLevel] = 'good'
        else
          if value >= fieldThreshold.poor
            holder[fieldLevel] = 'poor'
            @participantClassification = 3
          else if value >= fieldThreshold.warn
            holder[fieldLevel] = 'warn'
            @participantClassification = 2 if @participantClassification == 1
          else
            holder[fieldLevel] = 'good'

    classifyStats: (statBag) ->
      container = {}
      self = null
      for participant in statBag
        if participant.id == @app.clientId
          self = participant
          break

      for participant in statBag

        aggregate = {}

        @participantClassification = 1 # 1=good, 2=warn, 3=poor

        total_latency = 0

        if participant.cpu?
          system = {cpu: participant.cpu}

          @classify(system, 'cpu', SystemThresholds)

          participant.system = system

        network = participant.network

        if network?
          if network.audio_bitrate_rx > 0 && network.audio_bitrate_tx > 0
            @clientsWithAudio[participant.id] = true

          @classify(network, 'audiojq_median', NetworkThresholds)
          @classify(network, 'jitter_var', NetworkThresholds)
          @classify(network, 'audio_bitrate_rx', NetworkThresholds)
          @classify(network, 'audio_bitrate_tx', NetworkThresholds)
          @classify(network, 'video_rtpbw_tx', NetworkThresholds)
          @classify(network, 'video_rtpbw_rx', NetworkThresholds)
          @classify(network, 'ping', NetworkThresholds)
          @classify(network, 'pkt_loss', NetworkThresholds)
          @classify(network, 'wifi', NetworkThresholds)

          total_latency += network.ping / 2
          total_latency += network.audiojq_median * 2.5
          aggregate.one_way = network.ping / 2
          aggregate.jq = network.audiojq_median * 2.5

          # ARS TX/RX Determination
          #console.log("NETWORK", network)
          if network.ars_path_used == 0
            network.rx_ars_vs_p2p = 'P2P'
            if network.preferred_path == 'p2p'
              network.rx_ars_vs_p2p_level = 'good'
            else
              network.rx_ars_vs_p2p_level = 'warn'
          else
            network.rx_ars_vs_p2p = 'ARS'
            if network.preferred_path == 'p2p'
              network.rx_ars_vs_p2p_level = 'warn'
            else
              network.rx_ars_vs_p2p_level = 'good'

          if network.ars_con_active == 0
            network.tx_ars_vs_p2p = 'P2P'
            if network.preferred_path == 'p2p'
              network.tx_ars_vs_p2p_level = 'good'
            else
              network.tx_ars_vs_p2p_level = 'warn'
          else
            network.tx_ars_vs_p2p = 'ARS'
            if network.preferred_path == 'p2p'
              network.tx_ars_vs_p2p_level = 'warn'
            else
              network.tx_ars_vs_p2p_level = 'good'
        else
          total_latency = null

        audio = participant.audio

        if audio?
          if audio.cpu?
            system = {cpu: audio.cpu}
            @classify(system, 'cpu', SystemThresholds)
            participant.system = system

          if audio.in_latency? and audio.out_latency?
            audio.latency = audio.in_latency + audio.out_latency


          @classify(audio, 'framesize', AudioThresholds)
          @classify(audio, 'latency', AudioThresholds)
          @classify(audio, 'input_jitter', AudioThresholds)
          @classify(audio, 'output_jitter', AudioThresholds)
          @classify(audio, 'audio_in_type', AudioThresholds)

          if total_latency != null
            total_latency += audio.out_latency
            total_latency += self.audio.in_latency
            aggregate.their_out_latency = audio.out_latency
            aggregate.your_in_latency = self.audio.in_latency
        else
          total_latency = null

        if participant.id != @app.clientId

          aggregate.latency = total_latency

          @classify(aggregate, 'latency', AggregateThresholds)

          participant.aggregate = aggregate

        switch @participantClassification
          when 1 then participant.classification = 'good'
          when 2 then participant.classification = 'warn'
          when 3 then participant.classification = 'poor'
          else
            participant.classification = 'unknown'

        container[participant.id] = participant

      return container

    changed: () ->
      @clientsWithAudio = {}
      @stats = {}

      @stats = @classifyStats(@rawStats)
      if @parentStats
        @stats.parent = @classifyStats(@parentStats)
      else
        @stats.parent = null

      MixerActions.clientsWithAudio(@clientsWithAudio)

      # see if we can reset noAudio
      @trigger(@stats)
  }
)