context = window
logger = context.JK.logger

reactContext = if window.opener? then window.opener else window
# make sure this is actually us opening the window, not someone else (by checking for MixerStore)
if window.opener?
  console.log("WINDOW.opener", window.opener)
  try
    m = window.opener.MixerStore
    if !m?
      console.log("it's still not set")
      reactContext = window
  catch e
    reactContext = window


userAgent = window.navigator.userAgent;
if /iPhone|iPad|iPod|android/i.test(navigator.userAgent)
  # iPad or iPhone
  reactContext = window


VideoStore = reactContext.VideoStore
VideoActions = reactContext.VideoActions
PlatformStore = reactContext.PlatformStore

ALERT_NAMES = context.JK.ALERT_NAMES;

BackendNumericToBackendString = {
  1 :   "CIF    (352X288)",
  2 :   "VGA    (640X480)",
  3 :   "4CIF   (704X576)",
  4 :   "1/2WHD (640X360)",
  5 :   "WHD    (1280X720)",
  6 :   "FHD    (1920x1080)"
}


BackendToFrontendFPS = {
  1: 30,
  2: 24,
  3: 20,
  4: 15,
  5: 10
}

mixins = []
mixins.push(Reflux.listenTo(VideoStore, 'onVideoStateChanged'))

@WebcamViewer = React.createClass({

  mixins: mixins
  logger: context.JK.logger
  visible: false

  getInitialState: () ->
    {
      currentDevice: null
      deviceNames: {}
      deviceCaps: null
      currentCaptureResolution: 0
      captureResolutions: {}
      frameRates: {}
      rescanning: false
    }

  onVideoStateChanged: (changes) ->
    @setState(changes)

  render: () ->

    if @props.showBackBtn
      backBtn = `<a className="hidden button-grey back-btn" onClick={this.back}>BACK</a>`

    selectedDevice = this.selectedDeviceName(@state)

    # build list of webcams

    webcams = []
    noneSelected = selectedDevice == null || selectedDevice.length == 0

    # the backend does not allow setting no video camera.  So if a webcam is selected, prevent un-selecting
    if noneSelected
      webcams.push `<option key="none" value="" selected={noneSelected}>None Selected</option>`

    context._.each @state.deviceNames, (deviceName, deviceGuid) ->
      selected = deviceGuid == selectedDevice
      webcams.push `<option key={deviceGuid} value={deviceGuid} selected={selected}>{deviceName}</option>`

    noWebcams = Object.keys(@state.deviceNames).length == 0

    # build list of capture resolutions

    captureResolutions = []
    # load current settings from backend
    captureResolution = @state.currentCaptureResolution

    resolutions = @state.captureResolutions
    context._.each resolutions, (resolution, resolutionKey, obj) =>

      value = resolutionKey
      text = resolution

      selected = captureResolution.toString() == value.toString()

      captureResolutions.push `<option key={value} value={value} selected={selected}>{text}</option>`


    testBtnClassNames = {'button-orange' : true, 'webcam-test-btn' : true}
    if noWebcams
      if PlatformStore.isWindows()
        testBtnClassNames.disabled = !@state.videoEnabled
        testBtnClasses = classNames(testBtnClassNames)
        testBtn = `<a className={testBtnClasses} onClick={this.toggleWebcam}>TEST VIDEO</a>`
      else
        testBtn = null
    else if @state.videoShared
      testBtnClassNames.disabled = !@state.videoEnabled
      testBtnClasses = classNames(testBtnClassNames)
      testBtn = `<a className={testBtnClasses} onClick={this.toggleWebcam}>STOP WEBCAM</a>`
    else
      testBtnClassNames.disabled = !@state.videoEnabled || noneSelected
      testBtnClasses = classNames(testBtnClassNames)
      testBtn = `<a className={testBtnClasses} onClick={this.toggleWebcam}>TEST WEBCAM</a>`

    if @state.rescanning
      rescanning =
        `<span className="rescanning-notice">
          <span className="spinner-small" />
          CHECKING GEAR
        </span>`

    if @props.show_header
      if noWebcams
        if PlatformStore.isWindows()
          testVideoHelpText = `<span>The TEST VIDEO button will open the JamKazam video window to verify that receiving video works on your system.</span>`
        header = `<div className="video-header">
          <h2 className="subcaption">video gear:</h2>
          <div className="subcaption">
            JamKazam does not detect any webcams.  You will not be able to send video, but you can still receive it from others. {testVideoHelpText}
          </div>
        </div>`
      else
        header =
        `<div className="video-header">
          <h2 className="subcaption">video gear:</h2>
          <div className="subcaption">
            Select webcam to use for video in sessions.  Verify that you see video from webcam in the external application window (it may be behind this window).
          </div>
        </div>`

    if @state.videoEnabled
      disableVideoBtnText = "DISABLE VIDEO"
    else
      disableVideoBtnText = "ENABLE VIDEO"

    if @props.show_disable || !@state.videoEnabled || @state.everDisabled

      if @state.videoEnabled
        disableHelpBtn = `<a className="ftue-video-disable-help">[?]</a>`

      disableBtnClasses = classNames({'button-grey' : true, 'disable-video' : true, 'disabled' : @state.videoShared})
      disableVideo =
        `<div className="webcam-select-container wizard_control">
          <a className={disableBtnClasses} onClick={this.disableVideo}>{disableVideoBtnText}</a>
          {disableHelpBtn}
        </div>`

    `<div className="webcam-viewer">
      {header}
      <form className="video">
        <h2 className="sub-header select-webcam">select webcam:</h2>
        <div className="webcam-select-container wizard_control">
          <select onChange={this.selectWebcam} disabled={noWebcams || !this.state.videoEnabled}>
            {webcams}
          </select>
        </div>
        <h2 className="sub-header select-resolution">select video capture resolution:</h2>
        <div className="webcam-resolution-select-container wizard_control">
          <select onChange={this.selectResolution} disabled={noWebcams || !this.state.videoEnabled}>
            {captureResolutions}
          </select>
          <a className="ftue-video-settings-help">[?]</a>
        </div>
        <div className="configure-webcam wizard_control">
          {backBtn}
          {testBtn}
        </div>
        {rescanning}
      </form>
      {disableVideo}
    </div>`

  componentDidMount: () ->

    if @props.isVisible
      @beforeShow()

    $root = $(@getDOMNode())

    $videoSettingsHelp = $root.find('.ftue-video-settings-help')
    context.JK.helpBubble($videoSettingsHelp, 'ftue-video-settings', {}, {width:300}) if $videoSettingsHelp.length > 0
    $videoSettingsHelp.click(false)

    $videoDisableHelp = $root.find('.ftue-video-disable-help')
    context.JK.helpBubble($videoDisableHelp, 'ftue-video-disable', {}, {width:300}) if $videoDisableHelp.length > 0
    $videoDisableHelp.click(false)


  componentWillUpdate: (nextProps, nextState) ->
    # protect against non-video clients pointed at video-enabled server from getting into a session

    #@logger.debug("webcam devices", nextState.deviceNames, @state.deviceNames)

    if !@initialScan?
      @initialScan = true
    else if @visible
      @findChangedWebcams(nextState.deviceNames, @state.deviceNames)

  componentWillReceiveProps:(nextProps) ->
    if nextProps.isVisible
      @beforeShow()
    else
      @beforeHide()

  beforeShow:() ->

    @visible = true
    VideoActions.refresh()
    VideoActions.stopVideo()

    context.JK.onBackendEvent(ALERT_NAMES.USB_CONNECTED, 'webcam-viewer', @onUsbDeviceConnected);
    context.JK.onBackendEvent(ALERT_NAMES.USB_DISCONNECTED, 'webcam-viewer', @onUsbDeviceDisconnected);

  beforeHide: () ->

    @visible = false
    context.JK.offBackendEvent(ALERT_NAMES.USB_CONNECTED, 'webcam-viewer', @onUsbDeviceConnected);
    context.JK.offBackendEvent(ALERT_NAMES.USB_DISCONNECTED, 'webcam-viewer', @onUsbDeviceDisconnected);

    if @rescanTimeout?
      clearTimeout(@rescanTimeout)
      @rescanTimeout = null

    @setVideoOff()


  onUsbDeviceConnected: () ->
    # don't handle USB events when minimized
    #return if !context.jamClient.IsFrontendVisible()

    logger.debug("USB device connected")

    @scheduleRescanSystem(3000)

  onUsbDeviceDisconnected:() ->
    # don't handle USB events when minimized
    #return if !context.jamClient.IsFrontendVisible()

    logger.debug("USB device disconnected")

    @scheduleRescanSystem(3000)

  scheduleRescanSystem: (time) ->
    if @rescanTimeout?
      clearTimeout(@rescanTimeout)
      @rescanTimeout = null

    @setState({rescanning: true})
    @rescanTimeout = setTimeout(() =>
      @setState({rescanning: false})
      VideoActions.refresh()
    , time)

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

    device = $(e.target).val()

    VideoActions.selectDevice(device, {})

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

    return if @state.videoShared

    if @state.videoEnabled
      context.JK.Banner.showYesNo({
        title: "Disable Video?",
        html: "You will not be able to send or receive video.",
        yes: =>
          VideoActions.setVideoEnabled(false)
      })
    else
      VideoActions.setVideoEnabled(true)


  updateBackend: (captureResolution) ->
    @logger.debug 'Selecting capture resolution: ', captureResolution

    VideoActions.setCaptureResolution(captureResolution)

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

    resolution = $(e.target).val()
    @logger.debug 'new capture resolution selected: ' + resolution

    if resolution?
      @updateBackend(resolution)

  setVideoOff:() ->
    VideoActions.stopVideo()

  back: () =>
    window.location = '/client#/account'

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

    return unless this.state.videoEnabled

    $toggleBtn = $(e.target)

    # we should only do this if no device is currently selected
    $root = $(@getDOMNode())
    $select = $root.find('.webcam-select-container select')
    if Object.keys(@state.deviceNames).length == 0

      context.JK.Banner.showYesNo({
        yes_text: 'RUN TEST',
        title: "Run Video Test?",
        html: "A video window will show up with changing colors and shapes for 10 seconds.  The test was successful if you were able to see the changing colors.  Close the window once the colors and shapes stop changing.",
        yes: =>
          VideoActions.testVideo()
      })

    else
      device = $select.val()
      #VideoActions.selectDevice(device, {})
      if VideoStore.videoShared
        VideoActions.stopVideo()
      else
        VideoActions.toggleVideo()


    #if this.isVideoShared()
    #  $toggleBtn.removeClass("selected")
    #  VideoActions.stopVideo()
    #  @setState({videoShared: false})
    #else
    #  $toggleBtn.addClass("selected")
    #  VideoActions.startVideo()
    #  @setState({videoShared: true})

  selectedDeviceName:(state) ->
    webcamName = null
    # protect against non-video clients pointed at video-enabled server from getting into a session
    webcam = state.currentDevice
    #@logger.debug("currently selected video device", webcam)
    if (webcam? && Object.keys(webcam).length>0)
      webcamName = Object.keys(webcam)[0]

    webcamName

  findChangedWebcams: (newList, oldList) ->
    newKeys = Object.keys(newList)
    oldKeys = Object.keys(oldList)

    webcamSelect = $(@getDOMNode()).find('.webcam-select-container select')

    if newKeys.length > oldKeys.length
      for newKey in newKeys
        if oldKeys.indexOf(newKey) == -1
          newWebcam = newList[newKey]
          @logger.debug("new webcam found: " + newWebcam, newKey)
          context.JK.prodBubble(webcamSelect, 'new-webcam-found', {name: newWebcam}, {positions:['right']})
          break
    else if newKeys.length < oldKeys.length
      for oldKey in oldKeys
        if newKeys.indexOf(oldKey) == -1
          oldWebcam = oldList[oldKey]
          @logger.debug("webcam no longer found: " + oldWebcam)
          context.JK.prodBubble(webcamSelect, 'old-webcam-lost', {name: oldWebcam}, {positions:['right']})
          break


  }
)


