$ = jQuery
context = window
logger = context.JK.logger

@JamBlasterStore = Reflux.createStore(
  {
    listenables: @JamBlasterActions

    userJamBlasters: []
    localJamBlasters: []
    allJamBlasters: []
    waitingOnTracks: false

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

    onAppInit: (@app) ->

    postSimpleChange: (result, msg) ->
      if result
        setTimeout(()=>
          @lastClientTrackState = null
          console.log("GETLOCALCLIENTS: PostSimpleChange")
          @getLocalClients(@userJamBlasters)
        , 1000)

      else
        context.JK.Banner.showAlert('unable to update the JamBlaster', msg)

    onUpdateAudio: (name, value) ->
      # input1_linemode
      # input2_linemode
      # input1_48V
      # input2_48V
      # has_chat
      # track1 = {left, right, inst, stereo)
      # track1 = {left, right, inst, stereo)

      if @pairedJamBlaster? && @pairedJamBlaster.tracks?
        logger.debug("onUpdateAudio name=#{name} value=#{value}", @pairedJamBlaster.tracks)

        if name == 'inputTypeTrack1'
          result = context.jamClient.set48vAndLineInstState({input1_linemode: value})
          @postSimpleChange(result, 'Unable to set the line mode for Track 1')
          return

        else if name == 'inputTypeTrack2'
          result = context.jamClient.set48vAndLineInstState({input2_linemode: value})
          @postSimpleChange(result, 'Unable to set the line mode for Track 2')
          return

        else if name == 'track1Phantom'
          result = context.jamClient.set48vAndLineInstState({input1_48V: value})
          @postSimpleChange(result, 'Unable to set the phantom power for Track 1')
          return

        else if name == 'track2Phantom'
          result = context.jamClient.set48vAndLineInstState({input2_48V: value})
          @postSimpleChange(result, 'Unable to set the phantom power for Track 2')
          return

        #else if name == 'track1Instrument'
        #  result = context.jamClient.set48vAndLineInstState({input2_48V: value})
        #  @postSimpleChange(result, 'Unable to set the phantom power for Track 2')
        #  return

        #else if name == 'track1Instrument'
        #  result = context.jamClient.set48vAndLineInstState({input2_48V: value})
        #  @postSimpleChange(result, 'Unable to set the phantom power for Track 2')
        #  return


        audio = $.extend({}, @pairedJamBlaster.tracks)
        if name == 'inputTypeTrack1'
          audio.input1_linemode = value
        else if name == 'inputTypeTrack2'
          audio.input2_linemode = value
        else if name == 'track1Phantom'
          audio.input1_48V = value
        else if name == 'track2Phantom'
          audio.input2_48V = value
        else if name == 'micActive'
          audio.has_chat = value


        #track1Active = @pairedJamBlaster.tracks.track1Active
        #if name == 'track1Active'
        #  track1Active = value

        #track2Active = @pairedJamBlaster.tracks.track2Active
        #if name == 'track2Active'
        #  track2Active = value

        track1Active = true
        track2Active = true
        has_chat = true


        audio.has_chat = true

        combined = @pairedJamBlaster.tracks.combined
        if name == 'combined'
          combined = value

        track1Instrument = @pairedJamBlaster.tracks.track1Instrument
        track2Instrument = @pairedJamBlaster.tracks.track2Instrument
        if name == 'track1Instrument'
          track1Instrument = @convertToClientInstrument(value)
        if name == 'track2Instrument'
          track2Instrument = @convertToClientInstrument(value)

        if !track1Instrument
          track1Instrument = context.JK.server_to_client_instrument_map.Other.client_id
        if !track2Instrument
          track2Instrument = context.JK.server_to_client_instrument_map.Other.client_id


        if combined
          # user has chosen to combine both inputs into one track.  stereo=true is the key flag her

          audio.track1 = {stereo: true, left: true, inst: track1Instrument}
          delete audio.track2 # backend will treat null as present

        else

          if track1Active && track2Active

            audio.track1 = {stereo: false, left: true, inst: track1Instrument}
            audio.track2 = {stereo: false, right: true, inst: track2Instrument}

          else if track1Active   #(means track)

            audio.track1 = {stereo: false, left: true, inst: track1Instrument}
            delete audio.track2 #  backend will treat null as present

          else # input2Active

            audio.track2 = {stereo: false, right: true, inst: track2Instrument}
            delete audio.track1  # backend will treat null as present

        logger.debug("updating JamBlaster track state", audio)
        context.jamClient.setJbTrackState(audio);
        @waitOnTracks()
      else
        context.JK.Banner.showAlert('no paired JamBlaster', 'it seems your JamBlaster has become disconnected.  Please ensure it is powered on and connected via an ethernet cable.')

    waitOnTracks: () ->
      @lastClientTrackState = null
      @waitingOnTracks = true
      if @waitingOnTracksTimeout
        clearTimeout(@waitingOnTracksTimeout)
      @changed()
      @waitingOnTracksTimeout = setTimeout(() =>
        @waitingOnTracksTimeout = null
        if @waitingOnTracks
          @waitingOnTracks = false
          @changed()
          context.JK.Banner.showAlert('something went wrong', 'A notice that the changes were finally applied has not been sent.  Leave the session, restart the JamBlaster, and get into a session again.')
      , 10000)

    # called from backend after track thrashing
    jamblasterTracksUpdated: () ->
      if @waitingOnTracksTimeout
        clearTimeout(@waitingOnTracksTimeout)
        @waitingOnTracksTimeout = null
      @waitingOnTracks = false
      console.log("GETLOCALCLIENTS: jamblasterTracksUpdated")
      @getLocalClients(@userJamBlasters)
      @changed()

    convertToClientInstrument: (instrumentId) ->
      clientInstrumentId = null
      if instrumentId != null && instrumentId != ''
        clientInstrumentId = context.JK.instrument_id_to_instrument[instrumentId].client_id
      else
        clientInstrumentId = 10
      clientInstrumentId

    onSetAutoPair: (autopair) ->


      if !autopair
        context.jamClient.setJBAutoPair(autopair)
        @lastClientAutoPair = null
        JamBlasterActions.resyncBonjour()
        setTimeout((() => context.JK.Banner.showNotice("autoconnect removed",
          "To use the JamBlaster in the future, you will need to come to this screen and click the connect link.")), 1)
      else
        context.JK.Banner.showYesNo({
          title: "enable auto-connect",
          html: "If you would like to automatically connect to your JamBlaster whenever you start this app, click the AUTO CONNECT button below.",
          yes_text: 'AUTO CONNECT',
          yes: =>
            context.jamClient.setJBAutoPair(autopair)
            @lastClientAutoPair = null
            JamBlasterActions.resyncBonjour()
            setTimeout((() => context.JK.Banner.showNotice("autoconnect enabled",
              "Your desktop JamKazam application will automatically reconnect to the JamBlaster .")), 1)

        })

    onPairState: (state) ->
      if state.client_pair_state == 10
        # fully paired
        logger.debug("backend indicates we are paired with a client")
        @onResyncBonjour()

    onSaveNetworkSettings: (settings) ->
      logger.debug("onSaveNetworkSettings", settings)

      result = context.jamClient.setJbNetworkState(settings)
      if !result
        context.JK.Banner.showAlert('unable to save network settings', 'Please double-check that your JamBlaster is online and paired.')
        return
      else
        context.JK.Banner.showAlert('network settings updated', 'Please reboot the JamBlaster.')
        # it will be refreshed by backend
        setTimeout(()=>
          @onClearNetworkState()
          @onResyncBonjour()
        , 1000)


    onResyncBonjour: () ->

      if @refreshingBonjour
        logger.debug("already refreshing bonjour")
        return

      @refreshingBonjour = true
      @changed()
      rest.getUserJamBlasters({client_id: @app.clientId}).done((response) => @getUserJamBlastersDone(response)).fail((response) => @getUserJamBlastersFail(response))

    getUserJamBlastersDone: (response) ->
      @userJamBlasters = response

      @changed()

      console.log("GETLOCALCLIENTS: getUserJamBlastersDone")
      @getLocalClients(response)


    findJamBlaster: (oldClient) ->
      found = null
      if @clients?
        for client in @clients
          if oldClient.server_id? && client.server_id == oldClient.server_id
            found = client
            break
          if oldClient.ipv6_addr? && client.ipv6_addr == oldClient.ipv6_addr
            found = client
            break

      found

    getUserJamBlastersFail: (jqXHR) ->
      @refreshingBonjour = false
      @changed()
      @app.layout.ajaxError(jqXHR)

    getAutoPair: () ->
      if @lastClientAutoPair?
        return @lastClientAutoPair
      else
        return @getJbAutoPair()

    getNetworkState: (client) ->
      if @lastClientNetworkState? && @lastClientNetworkState.ipv6_addr == client.ipv6_addr
        return @lastClientNetworkState
      else
        return @getJbNetworkState(client)

    getPortState: (client) ->
      if @lastClientPortState? && @lastClientPortState.ipv6_addr == client.ipv6_addr
        return @lastClientPortState
      else
        return @getJbPortBindState(client)

    getJbPortBindState:(client) ->
      @lastClientPortState = context.jamClient.getJbPortBindState()
      console.log("context.jamClient.getJbPortBindState()", @lastClientPortState)
      @lastClientPortState.ipv6_addr = client.ipv6_addr
      return @lastClientPortState

    getJbNetworkState:(client) ->
      @lastClientNetworkState = context.jamClient.getJbNetworkState()
      console.log("context.jamClient.getJbNetworkState()", @lastClientNetworkState)
      @lastClientNetworkState.ipv6_addr = client.ipv6_addr
      return @lastClientNetworkState

    getJbAutoPair:() ->
      @lastClientAutoPair = context.jamClient.getJBAutoPair()
      console.log("context.jamClient.getJBAutoPair()", @lastClientAutoPair)
      return @lastClientAutoPair

    getJbTrackState:(client) ->
      @lastClientTrackState = context.jamClient.getJbTrackState()
      console.log("context.jamClient.getJbTrackState()", @lastClientTrackState)
      @lastClientTrackState.ipv6_addr = client.ipv6_addr
      return @lastClientTrackState

    onClearPortBindState: () ->
      @lastClientPortState = null

    onClearNetworkState: () ->
      @lastClientNetworkState = null

    mergeBonjourClients: (localClients, userJamBlasters) ->
      console.log("@state.localClients", localClients)
      console.log("@state.userJamBlasters", userJamBlasters)

      # for localClient in @state.localClients

      autoconnect = @getAutoPair()

      foundPaired = null
      clients = []
      for localClient in localClients
        if localClient.connect_url.indexOf(':30330') > -1 && localClient.is_jb
          client = {}
          client.ipv6_addr = localClient.ipv6_addr
          client.isConnected = localClient.isPaired
          client.name = localClient.name
          client.has_local = true
          client.has_server = false
          client.id = client.ipv6_addr
          client.connect_url = localClient.connect_url
          client.isPaired = localClient.pstate? && localClient.pstate == 10 # ePairingState.Paired
          client.autoconnect = autoconnect

          if client.isPaired
            client.portState = @getPortState(client)
            client.network = @getNetworkState(client)
            client.tracks = @getJbTrackState(client)
            client.isDynamicPorts = client.portState?.use_static_port
            foundPaired = client


            if client.tracks?
              client.tracks.inputTypeTrack1 = client.tracks.input1_linemode
              client.tracks.inputTypeTrack2 = client.tracks.input2_linemode
              client.tracks.track1Phantom = client.tracks.input1_48V
              client.tracks.track2Phantom = client.tracks.input2_48V
              client.tracks.micActive = client.tracks.has_chat

              # combined
              track1 = client.tracks.track1
              track2 = client.tracks.track2
              if track1?

                client.tracks.combined = track1.stereo
                if track1.stereo
                  client.tracks.track1Active = true
                  client.tracks.track2Active = true
                client.tracks.track1Active = track1.left
                client.tracks.track2Active = track1.right
                client.tracks.track1Instrument = track1.inst

              if track2?
                client.tracks.track2Instrument = track2.inst
                client.tracks.track1Active = track2.left
                client.tracks.track2Active = track2.right
                  # 	map["adaptiveframe"] = jbcfg.adaptiveframe();






          for serverClient in userJamBlasters
            # see if we can join on ipv6
            if ipv6_addr == serverClient.ipv6_link_local
              # ok, matched! augment with server data
              client.serial_no = serverClient.serial_no
              client.user_id = serverClient.user_id
              client.id = serverClient.id
              client.server_id = serverClient.id
              client.client_id = serverClient.client_id
              client.ipv4_link_local = serverClient.ipv4_link_local
              client.display_name = serverClient.display_name
              client.has_server = true
              break
          clients.push(client)

      for serverClient in userJamBlasters

        foundLocal = false
        for localClient in localClients
          if ipv6_addr == serverClient.ipv6_link_local
            foundLocal = true
            break
        if !foundLocal
          # this server version of the client has not been spoken for in the earlier loop above
          # so we need to add it in to the client list

          client = {}
          client.serial_no = serverClient.serial_no
          client.user_id = serverClient.user_id
          client.id = serverClient.id
          client.client_id = serverClient.client_id
          client.ipv4_link_local = serverClient.ipv4_link_local
          client.display_name = serverClient.display_name
          client.has_local = false
          client.has_server = true
          client.autoconnect = autoconnect
          clients.push(client)

      @pairedJamBlaster = foundPaired

      console.log("all client", clients)

      @clients = clients
      @changed()

    getLocalClients: (userJamBlasters) ->
      @localClients = context.jamClient.getLocalClients()

      @mergeBonjourClients(@localClients, userJamBlasters)

      @refreshingBonjour = false
      @changed()

    get48vAndLineState: () ->
      @phantomAndLineState = context.jamClient.get48vAndLineInstState()
      console.log("get48vAndLineInstState", @phantomAndLineState)


    changed: () ->
      @trigger({userJamBlasters: @userJamBlasters, allJamBlasters: @clients, localJamBlasters: @localClients, refreshingBonjour: @refreshingBonjour, pairedJamBlaster: @pairedJamBlaster, waitingOnTracks: @waitingOnTracks})
  }
)
