context = window
rest = context.JK.Rest()
logger = context.JK.logger
JamBlasterActions = @JamBlasterActions

@JamBlasterScreen = React.createClass({

  mixins: [
    @ICheckMixin,
    @PostProcessorMixin,
    @BonjourMixin,
    Reflux.listenTo(AppStore, "onAppInit"),
    Reflux.listenTo(UserStore, "onUserChanged"),
    Reflux.listenTo(JamBlasterStore, "onJamBlasterChanged")
  ]

  TILE_AUDIO: 'audio'
  TILE_INTERNET: 'internet'
  TILE_MANAGEMENT: 'management'
  TILE_USB: 'usb'

  TILES: ['management', 'audio', 'internet']

  networkStale: false
  ipRegex:  /^0([0-9])+/

  onAppInit: (@app) ->
    @app.bindScreen('jamblaster',
      {beforeShow: @beforeShow, afterShow: @afterShow, beforeHide: @beforeHide})

  onUserChanged: (userState) ->
    @setState({user: userState?.user})

  onJamBlasterChanged: (jamblasterState) ->
    @setState(jamblasterState)

  componentDidMount: () ->
    @checkboxes = [{selector: 'input.dhcp', stateKey: 'userdhcp'}]
    @root = $(@getDOMNode())
    @iCheckify()



  componentDidUpdate: () ->
    @iCheckify()

    items = @root.find('.jamtable .optionsColumn .jamblaster-options-btn')

    $.each(items, (i, node) => (
      $node = $(node)

      jamblaster = @findJamBlaster({
        server_id: $node.attr('data-jamblaster-id'),
        ipv6_addr: $node.attr('data-jamblaster-addr')
      })

      $node.jamblasterOptions(jamblaster).off(context.JK.EVENTS.JAMBLASTER_ACTION).on(context.JK.EVENTS.JAMBLASTER_ACTION,
        @jamblasterOptionSelected)
    ))

    @root.find('input.networksettings').inputmask({
      alias: "ip",
      "placeholder": "_"
    });

  checkboxChanged: (e) ->
    checked = $(e.target).is(':checked')

    value = $(e.target).val()
    console.log("checkbox changed: ", value)


    @setState({userdhcp: "true" == value})

  componentWillUpdate: (nextProps, nextState) ->
    if @networkStale && @state.pairedJamBlaster?
      console.log("stale network update", @state)
      nextState.userdhcp     = @state.pairedJamBlaster.network?.dhcp
      nextState.useraddr     = @state.pairedJamBlaster.network?.addr
      nextState.usersubnet   = @state.pairedJamBlaster.network?.subnet
      nextState.usergateway  = @state.pairedJamBlaster.network?.gateway
      nextState.userdns1     = @state.pairedJamBlaster.network?.dns1
      nextState.userdns2     = @state.pairedJamBlaster.network?.dns2
      nextState.userdhcperror     = false
      nextState.useraddrerror     = false
      nextState.usersubneterror   = false
      nextState.usergatewayerror  = false
      nextState.userdns1error     = false
      nextState.userdns2error     = false
      @networkStale = false

#context.JK.popExternalLinks(@root)

  jamblasterOptionSelected: (e, data) ->
    jamblaster = data.options
    jamblaster = @findJamBlaster(jamblaster)

    if data.option == 'auto-connect'
      JamBlasterActions.setAutoPair(!jamblaster.autoconnect)
    else if data.option == 'restart'
      context.JK.Banner.showYesNo({
        title: "reboot JamBlaster",
        html: "Are you sure?"
        yes: =>
          result = context.jamClient.rebootJamBlaster()
          if result
            setTimeout((() => context.JK.Banner.showNotice("JamBlaster is rebooting",
              "It should be back online within a minute.")), 1)
            setTimeout((() => JamBlasterActions.resyncBonjour()), 1000)

          else
            setTimeout((() => context.JK.Banner.showAlert("could not reboot",
              "The JamBlaster could not be rebooted remotely.  Please cycle the power manually.")), 1)

      })

    else if data.option == 'name'
      @app.layout.showDialog('jamblaster-name-dialog', {d1: jamblaster.name}).one(context.JK.EVENTS.DIALOG_CLOSED,
        (e, data) =>
          setTimeout((() => JamBlasterActions.resyncBonjour()), 1000)
      )

    else if data.option == 'check-for-updates'
      context.JK.Banner.showNotice('Check for Update',
        'The JamBlaster only checks for updates when booting up.  Please reboot the JamBlaster to initiate an update check.')
    else if data.option == 'set-static-ports'
      if jamblaster.isDynamicPorts
        context.JK.Banner.showYesNo({
          title: "revert to dynamic ports",
          html: "Your JamBlaster is currently configured to use ports #{jamblaster.portState.static_port} - #{jamblaster.portState.static_port + 10}).  Would you like to revert to the use of dynamic ports for UDP communication?"
          yes: =>
            context.jamClient.setJbPortBindState({use_static_port: false, static_port: 12000})
            JamBlasterActions.clearPortBindState()
            #setTimeout((() => JamBlasterActions.resyncBonjour()), 1000)
            JamBlasterActions.resyncBonjour()
            setTimeout((() => context.JK.Banner.showNotice("reboot JamBlaster",
              "For these settings to take effect, you must restart the JamBlaster.")), 1)

        })

      else
        @app.layout.showDialog('jamblaster-port-dialog').one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) =>
          JamBlasterActions.clearPortBindState()
          JamBlasterActions.resyncBonjour()
          context.JK.Banner.showNotice("reboot JamBlaster",
            "For these settings to take effect, you must restart the JamBlaster.")
        )
    else if data.option == 'factory-reset'
      context.JK.Banner.showNotice('Factory Reset',
        'The JamBlaster only checks for updates when it boots up, and if there is an update available, it will automatically begin updating.<br/><br/>Please reboot the JamBlaster to initiate an update check.')
    else
      logger.debug("unknown action")
  getInitialState: () ->
    {
    selected: 'management',
    user: null,
    userJamBlasters: [],
    localJamBlasters: [],
    allJamBlasters: []
    }

  beforeHide: (e) ->
    @clearTimer()

  beforeShow: (e) ->
    @setTimer()

  afterShow: (e) ->
    JamBlasterActions.resyncBonjour()

  openMenu: (client, e) ->
    logger.debug("open jamblaster options menu")
    $this = $(e.target)
    if !$this.is('.jamblaster-options-btn')
      $this = $this.closest('.jamblaster-options-btn')
    $this.btOn()

  clearTimer: () ->
    if @interval?
      clearInterval(@interval)
      @interval = null

# Refresh bonjour status every 30 second, so that we catch major changes
  setTimer: () ->
    @clearTimer()
    time = 30000 # every 30 seconds

    @interval = setInterval((() => JamBlasterActions.resyncBonjour()), time)

  connect: (client, e) ->
    logger.debug("beginning pairing to #{client.connect_url}")

    @clearTimer()
    @app.layout.showDialog('jamblaster-pairing-dialog', {d1: client}).one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) =>
      JamBlasterActions.resyncBonjour()
      @setTimer()
    )
  disconnect: (client, e) ->
    logger.debug("disconnecting from currently paired client #{client.connect_url}")
    context.jamClient.endPairing()
    setTimeout((() => JamBlasterActions.resyncBonjour()), 1000)

  mergeClients: () ->
    clientsJsx = []
    for client in @state.allJamBlasters
      if client.display_name?
        displayName = client.display_name
      else
        displayName = client.name

      if client.serial_no? && displayName? && displayName.indexOf(client.serial_no) == -1
        displayName = "#{displayName} (#{client.serial_no})"
      name = `<span className="displayNameColumn">{displayName}</span>`

      if client.isPaired
        connect = `<span className="connectColumn"><a
          onClick={this.disconnect.bind(this, client)}>disconnect</a></span>`
      else if client.has_local
        connect = `<span className="connectColumn"><a onClick={this.connect.bind(this, client)}>connect</a></span>`
      else
        connect = `<span className="connectColumn">offline</span>`

      options = `<span className="optionsColumn"><a data-jamblaster-id={client.server_id}
                                                    data-jamblaster-addr={client.ipv6_addr}
                                                    className="jamblaster-options-btn"
                                                    onClick={this.openMenu.bind(this, client)}>more options
        <div className="details-arrow arrow-down"/>
      </a></span>`

      clientsJsx.push(`<tr>
        <td>{name}{options}{connect}</td>
      </tr>`)

    clientsJsx

  mainContent: () ->
    if !@state.user?.id || !@state.userJamBlasters? || !@state.localJamBlasters?
      return `<div>Loading ...</div>`


    if @state.selected == @TILE_AUDIO
      @audio()
    else if @state.selected == @TILE_INTERNET
      @internet()
    else if @state.selected == @TILE_MANAGEMENT
      @management()
    else if @state.selected == @TILE_USB
      @usb()

  audio: () ->
    `<div className="audio-content">
      To edit the JamBlaster audio settings, get into a session, and click the Settings link under My Tracks.
    </div>`

  ipSettingsChanged: (key, e) ->
    userKey = 'user' + key
    state = {}
    ip = $(e.target).val()
    state[userKey] = ip
    if ip?
      bits = ip.split('.')

      console.log("bits", bits)
      for bit in bits
        result = @ipRegex.test(bit.replace(/_/g, ''))
        console.log("STILL GOT THAT _?", result)
        error = false
        if result == true || bit == "___"
           error = true
           break

      if error
        console.log("SETTING ERROR for " + userKey + 'error')
        state[userKey + 'error'] = true
      else
        state[userKey + 'error'] = false
    this.setState(state)

  onSaveNetworkSettings: (e) ->
    e.preventDefault()

    settings = {
      dhcp: this.state.userdhcp,
      addr: this.state.useraddr,
      gateway: this.state.usergateway,
      subnet: this.state.usersubnet,
      dns1: this.state.userdns1,
      dns2: this.state.userdns2
    }

    logger.debug("saving network settings", settings)
    JamBlasterActions.saveNetworkSettings(settings)
    @networkStale = true

  usb: () ->
    `<div className="networking-content">
      <h3>USB Settings</h3>
    </div>`

  internet: () ->
    pairedJamBlaster = this.state.pairedJamBlaster
    hasPairedJamBlaster = pairedJamBlaster?
    isJamBlasterDhcp = !!this.state.userdhcp

    if hasPairedJamBlaster
      status =
        `<div className="jamblaster-network-status">
          <div className="status-field"><span className="status-label">Ethernet:</span><span>Connected</span></div>
          <div className="status-field"><span className="status-label">Internet:</span><span>Connected</span></div>
          <div className="status-field"><span className="status-label">Streaming:</span><span>Supported</span></div>
      </div>`
    else
      status =
        `<div className="jamblaster-network-status">
          <div className="status-field"><span className="status-label">Ethernet:</span><span>Unknown</span></div>
          <div className="status-field"><span className="status-label">Internet:</span><span>Unknown</span></div>
          <div className="status-field"><span className="status-label">Streaming:</span><span>Unknown</span></div>
        </div>`

    addrClasses     = {field: true, error: this.state.useraddrerror}
    subnetClasses   = {field: true, error: this.state.usersubneterror}
    gatewayClasses  = {field: true, error: this.state.usergatewayerror}
    dns1Classes     = {field: true, error: this.state.userdns1error}
    dns2Classes     = {field: true, error: this.state.userdns2error}

    saveBtnClasses = {}
    saveBtnClasses["save-settings-btn"] = true
    saveBtnClasses["button-orange"] = true
    saveBtnClasses["disabled"] = !hasPairedJamBlaster

    ipdisabled = !hasPairedJamBlaster || isJamBlasterDhcp

    `<div className="networking-content">
      <h3>Internet Settings</h3>

      <div className="column-left column">
        <div className="assign-ip-address">
          <h4>Assign IP Address</h4>

          <div className="dhcpfield">
            <input className="dhcp" type="radio" name="dhcp" readOnly={true} value="true" defaultChecked={isJamBlasterDhcp}
                   disabled={!hasPairedJamBlaster}/><label>Using DHCP</label>
          </div>
          <div className="dhcpfield">
            <input className="dhcp" type="radio" name="dhcp" readOnly={true} value="false" defaultChecked={!isJamBlasterDhcp}
                   disabled={!hasPairedJamBlaster}/><label>Manually</label>
          </div>
        </div>
        <div className="manual-settings">
          <h4>Manual Settings</h4>
          <div className={classNames(addrClasses)}>
            <label>IP Address:</label><input className="addr networksettings" type="text" value={this.state.useraddr} name="addr" onBlur={this.ipSettingsChanged.bind(this, 'addr')} disabled={ipdisabled}></input>
          </div>
          <div className={classNames(subnetClasses)}>
            <label>Subnet Mask:</label><input className="subnet networksettings" type="text" value={this.state.usersubnet} name="subnet" onBlur={this.ipSettingsChanged.bind(this, 'subnet')} disabled={ipdisabled}></input>
          </div>
          <div className={classNames(gatewayClasses)}>
            <label>Router:</label><input className="gateway networksettings" type="text" value={this.state.usergateway} name="gateway" onBlur={this.ipSettingsChanged.bind(this, 'gateway')} disabled={ipdisabled}></input>
          </div>
          <div className={classNames(dns1Classes)}>
            <label>DNS Server 1:</label><input className="dns1 networksettings" type="text" value={this.state.userdns1} name="dns1" onBlur={this.ipSettingsChanged.bind(this, 'dns1')} disabled={ipdisabled}></input>
          </div>
          <div className={classNames(dns1Classes)}>
            <label>DNS Server 2:</label><input className="dns2 networksettings" type="text" value={this.state.userdns2} name="dns1" onBlur={this.ipSettingsChanged.bind(this, 'dns2')} disabled={ipdisabled}></input>
          </div>

        </div>
        <div className="save-settings">
          <a onClick={this.onSaveNetworkSettings} className={classNames(saveBtnClasses)}>SAVE SETTINGS</a>
        </div>
      </div>
      <div className="column-right column">
        <h4>Network Status</h4>
        {status}
      </div>
    </div>`

  management: () ->
    clients = @mergeClients()
    if @state.refreshingBonjour
      refreshingText = 'SCANNING'
    else
      refreshingText = 'SCAN NETWORK'

    refreshClasses = {"resync-bonjour": true, "button-orange": true, disabled: @state.refreshingBonjour}
    `<div className="management-content">

      <table className="jamtable">
        <thead>
        <tr>
          <th className="jamblasterColumn">JAMBLASTERS ON YOUR NETWORK</th>
        </tr>
        </thead>
        <tbody>
        {clients}
        </tbody>
      </table>
      <a onClick={JamBlasterActions.resyncBonjour} className={classNames(refreshClasses)}>{refreshingText}</a>

      <p className="help-text">If you don't see your JamBlaster listed above, please check to make sure you have power
        connected to your JamBlaster,
        and make sure your JamBlaster is connected via an Ethernet cable to the same router/network as the device on
        which you are viewing this application.
      </p>
    </div>`

  tiles: () ->
    @TILES

  selectionMade: (selection, e) ->
    e.preventDefault()

    if selection == @TILE_INTERNET
      @networkStale = true

    @setState({selected: selection})

  createTileLink: (i, tile) ->
    if this.state.selected?
      active = this.state.selected == tile
    else
      active = tile == @TILE_MANAGEMENT

    tileClasses = {activeTile: active, 'jamblaster-tile': true}
    tileClasses = classNames(tileClasses)

    classes = classNames({last: i == @tiles().length - 1})

    return `<div key={i} className={tileClasses}><a className={classes}
                                                    onClick={this.selectionMade.bind(this, tile)}>{tile}</a></div>`

  render: () ->
    disabled = @state.updating

    tiles = []
    for tile, i in @tiles()
      tiles.push(@createTileLink(i, tile))

    `<div className="content-body-scroller">
      <div className="">
        <h2>jamblaster settings</h2>

        <div className="tiles">
          {tiles}
        </div>

        <div className="jamclass-section">
          {this.mainContent()}
        </div>
      </div>
      <br className="clearall"/>
    </div>`
})