context = window
logger = context.JK.logger
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
rest = context.JK.Rest()

mixins = []


# make sure this is actually us opening the window, not someone else (by checking for MixerStore)

accessOpener = false
if window.opener?
  try
    m = window.opener.MixerStore
    accessOpener = true
  catch e


if accessOpener
  AppActions = window.opener.AppActions
  SessionActions = window.opener.SessionActions
  MixerActions = window.opener.MixerActions
  MixerStore = window.opener.MixerStore
  JamTrackActions = window.opener.JamTrackActions
  JamTrackMixdownActions = window.opener.JamTrackMixdownActions
  #JamTrackMixdownStore = window.opener.JamTrackMixdownStore
  JamTrackMixdown = window.opener.JamTrackMixdown
  JamTrackStore = window.opener.JamTrackStore
  MixerStore = window.opener.MixerStore
  SessionStore = window.opener.SessionStore
  UserStore = window.opener.UserStore

mixins.push(Reflux.listenTo(MixerStore, 'onMixersChanged'))
mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
mixins.push(Reflux.listenTo(UserStore, 'onUserChanged'))

@PopupMediaControls = React.createClass({

  mixins: mixins

  updateFromMixerHelper: (mixers, session) ->


    # the backend delete/adds the metronome rapidly when the user hits play. this is custom code to deal with that

    state =
      isRecording: session.isRecording
      mediaSummary: mixers.mediaSummary
      backingTracks: mixers.backingTracks
      jamTracks: mixers.jamTracks
      recordedTracks: mixers.recordedTracks
      metronome: mixers.metronome
      recordingName: mixers.recordingName()
      jamTrackName: mixers.jamTrackName()
      jamTrackMixdown: session.jamTrackMixdown()

    return {media: state, downloadingJamTrack: session.downloadingJamTrack}

  onMixersChanged: (sessionMixers) ->
    session = sessionMixers.session
    mixers = sessionMixers.mixers

    if @unloaded
      #console.log("PopupMediaControls unloaded. ignore onMixersChnaged")
      return
    if window.closed
      return
    @setState(@updateFromMixerHelper(mixers, session))


  onMediaStateChanged: (changes) ->
    if @unloaded
      #console.log("PopupMediaControls unloaded. ignore onMixersChnaged")
      return

    if window.closed
      return

    if changes.currentTimeChanged && @root?
      @setState({time: changes.time})

  onJamTrackChanged: (changes) ->
    if @unloaded
      #console.log("PopupMediaControls unloaded. ignore onMixersChnaged")
      return

    if window.closed
      return

    logger.debug("PopupMediaControls: jamtrack changed", changes)
    @setState({jamTrackState: changes})

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

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

    SessionActions.showNativeMetronomeGui()

  getInitialState: () ->

    if accessOpener

      state = @updateFromMixerHelper(MixerStore.mixers, MixerStore.session)
      state.jamTrackState = JamTrackStore.getState()
      state.user = UserStore.getState().user
      return state
    else

    return {
      media: @props.media,
      mixdown: @props.mixdown,
      jamTrackState: @props.jamTrackState,
      creatingMixdown: false,
      createMixdownErrors: null,
      editingMixdownId: null,
      downloadingJamTrack: @props.downloadingJamTrack,
      jamTrackMixdown: {}
    }

  close: (e) ->
    if e?
      e.preventDefault()

    if !@state.media.mediaSummary.isOpener && !@state.media.mediaSummary.metronomeOpen
      SessionActions.log({msg: "isOpener=" + state.media.mediaSummary.isOpener})
      SessionActions.log({msg: "metronomeOpen=" + state.media.mediaSummary.metronomeOpen})
      return

    SessionActions.log({msg: "PopupMediaControls close event trigger"})
    window.close()

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

    AppActions.openExternalUrl($(e.target).attr('href'))

  render: () ->

    closeLinkText = null
    header = null
    extraControls = null

    # give the users options to close it
    if @state.media.mediaSummary.recordingOpen
      mediaType = "Recording"
      mediaName = @state.media.recordedTracks[0].recordingName
      closeLinkText = 'close recording'
      header = `<h3>{mediaType}: {mediaName}</h3>`
    else if @state.media.mediaSummary.jamTrackOpen || @state.jamTrackState.jamTrack?
      if @state.media.mediaSummary.isOpener || @state.jamTrackState.jamTrack?
        # if you opened the JamTrack, then you get all the good info
        jamTrack = @state.jamTrackState.jamTrack
        mediaType = "JamTrack"
        mediaName = jamTrack.name
        closeLinkText = 'CLOSE JAMTRACK'
        helpLink = 'https://jamkazam.desk.com/customer/portal/articles/2138903-using-custom-mixes-to-slow-tempo-change-pitch'

        selectedMixdown = jamTrack.activeMixdown


        if selectedMixdown?
          jamTrackTypeHeader = 'Custom Mix'

          disabled = true
          if selectedMixdown.client_state?
            switch selectedMixdown.client_state
              when 'cant_open'
                customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
              when 'keying_timeout'
                customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
              when 'download_fail'
                customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
              when 'keying'
                customMixName = `<h5>Loading selected mix... <img src="/assets/shared/spinner.gif" /></h5>`
              when 'downloading'
                customMixName = `<h5>Loading selected mix... <img src="/assets/shared/spinner.gif" /></h5>`
              when 'ready'
                customMixName = `<h5>{selectedMixdown.name}</h5>`
                disabled = false
          else
            if selectedMixdown.myPackage
              customMixName = `<h5>Creating mixdown... <img src="/assets/shared/spinner.gif" /></h5>`
            else
              customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`

        else
          if SessionStore.downloadingJamTrack
            downloader = `<img src="/assets/shared/spinner.gif" />`

          jamTrackTypeHeader = `<span>Full JamTrack {downloader}</span>`

        header = `
        <div className="header">
          <h3>{mediaType}: {mediaName}</h3>
          <h4>{jamTrackTypeHeader}</h4>
          {customMixName}
        </div>`

        myMixes = null
        if @state.showMyMixes
          myMixdowns = []

          boundPlayClick = this.jamTrackPlay.bind(this, jamTrack);
          boundDownloadClick = this.jamTrackDownload.bind(this, jamTrack);

          active = jamTrack.last_mixdown_id == null

          myMixdowns.push `
            <div key="full-track" className={classNames({'full-track': true, 'mixdown-display': true, 'active' : active})}>
              <div className="mixdown-name">
                Full JamTrack
              </div>
              <div className="mixdown-actions">
                <img src="/assets/content/icon_open@2X.png" className="mixdown-play" onClick={boundPlayClick}/>
                <img src="/assets/content/icon_download@2X.png" className="mixdown-download" onClick={boundDownloadClick}/>
                <img src ="/assets/content/icon-delete@2X.png" style={{visibility:'hidden'}} className="mixdown-edit" onClick={false} />
                <img src ="/assets/content/icon-delete@2X.png" style={{visibility:'hidden'}} className="mixdown-delete" onClick={false} />
              </div>
            </div>`

          for mixdown in jamTrack.mixdowns
            boundPlayClick = this.mixdownPlay.bind(this, mixdown);
            boundEditClick = this.mixdownEdit.bind(this, mixdown);
            boundSaveClick = this.mixdownSave.bind(this, mixdown);
            boundDeleteClick = this.mixdownDelete.bind(this, mixdown);
            boundErrorClick = this.mixdownError.bind(this, mixdown);
            boundEditKeydown = this.onEditKeydown.bind(this, mixdown);
            boundDownloadReadyClick = this.downloadMixdownReady.bind(this, mixdown)

            mixdown_package = mixdown.myPackage

            active = mixdown.id == jamTrack.last_mixdown_id

            editing = mixdown.id == @state.editingMixdownId

            # if there is a package, check it's state; otherwise let the user enqueue it
            if mixdown_package
              switch mixdown_package.signing_state
                when 'QUIET_TIMEOUT'
                  action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
                when 'QUIET'
                  action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
                when 'QUEUED'
                  action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
                when 'QUEUED_TIMEOUT'
                  action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
                when 'SIGNING'
                  action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
                when 'SIGNING_TIMEOUT'
                  action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
                when 'SIGNED'
                  action = `<img src="/assets/content/icon_open@2X.png" className="mixdown-play" onClick={boundPlayClick}/>`
                when 'ERROR'
                  action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
            else
              action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`

            if editing
              mixdownName = `<input className="edit-name" type="text" defaultValue={mixdown.name} onKeyDown={boundEditKeydown}  />`
              editIcon = `<img src="/assets/content/icon-save@2X.png" className="mixdown-edit" onClick={boundSaveClick}/>`
            else
              mixdownName = mixdown.name
              editIcon = `<img src="/assets/content/icon-edit@2X.png" className="mixdown-edit" onClick={boundEditClick}/>`

            download = `<img src="/assets/content/icon_download@2X.png" className="mixdown-download" onClick={boundDownloadReadyClick} />`

            myMixdowns.push `
            <div key={mixdown.id} className={classNames({'mixdown-display': true, 'active' : active})}>
              <div className="mixdown-name">
                {mixdownName}
              </div>
              <div className="mixdown-actions">
                {action}
                {download}
                {editIcon}

                <img src ="/assets/content/icon-delete@2X.png" className="mixdown-delete" onClick={boundDeleteClick} />
              </div>
            </div>`

          trackOptions = []
          for track in jamTrack.tracks
            if track.track_type == 'Track' || track.track_type == 'Click'

              if track.instrument
                instrumentId = track.instrument.id
                instrumentDescription = track.instrument.description
                if track.part? && track.part != instrumentDescription
                  part = "(#{track.part})"
                else
                  part = ''
              trackOptions.push(`<option key={track.id} value={track.id}>{instrumentDescription} {part}</option>`)

          myMixdowns.push `
              <div key={track.id} className={classNames({'stem-track' : true, 'mixdown-display': true})}>
                <div className="mixdown-name">
                  <select className="active-stem-select" name="active-stem-select" onChange={this.stemChanged}>
                    <option key="null" value="">or select a track</option>
                    {trackOptions}
                  </select>
                </div>
                <div className="mixdown-actions">
                  <img src="/assets/content/icon_open@2X.png" style={{visibility:'hidden'}} className="mixdown-play"/>
                  <img src="/assets/content/icon_download@2X.png" className="mixdown-download" onClick={this.stemDownload}/>
                  <img src ="/assets/content/icon-delete@2X.png" style={{visibility:'hidden'}} className="mixdown-edit" onClick={false} />
                  <img src ="/assets/content/icon-delete@2X.png" style={{visibility:'hidden'}} className="mixdown-delete" onClick={false} />
                </div>
              </div>`

          myMixes = `<div key="my-mixes" className="my-mixes">{myMixdowns}</div>`

        mixControls = null
        if @state.showCustomMixes

          nameClassData = {field: true}
          if @state.createMixdownErrors?

            errorHtml = context.JK.reactErrors(@state.createMixdownErrors, {name: 'Mix Name', settings: 'Settings', jam_track: 'JamTrack'})

          createMixClasses = classNames({'button-orange' : true, 'create-mix-btn' : true, 'disabled' : @state.creatingMixdown})

          if !selectedMixdown?
            mixControls = `
              <div key="create-mix" className="create-mix">
                <p>Use the JamTrack controls on the session screen to set levels, mute/unmute, or pan any of the parts of the JamTrack as you like. You can also use the controls below to adjust the tempo or pitch of the JamTrack. Then give your custom mix a name, and click the Create Mix button.</p>
                <div className="field">
                  <label>Change Tempo:</label>
                  <select name="mix-speed">
                    <option value="">No change</option>
                    <option value="separator-1">------------</option>
                    <option value="-5">Slower by 5%</option>
                    <option value="-10">Slower by 10%</option>
                      <option value="-15">Slower by 15%</option>
                    <option value="-20">Slower by 20%</option>
                    <option value="-25">Slower by 25%</option>
                    <option value="-30">Slower by 30%</option>
                    <option value="-35">Slower by 35%</option>
                    <option value="-40">Slower by 40%</option>
                    <option value="-45">Slower by 45%</option>
                    <option value="-50">Slower by 50%</option>
                    <option value="-60">Slower by 60%</option>
                    <option value="-70">Slower by 70%</option>
                    <option value="-80">Slower by 80%</option>
                    <option value="separator-2">------------</option>
                    <option value="5">Faster by 5%</option>
                    <option value="10">Faster by 10%</option>
                    <option value="15">Faster by 15%</option>
                    <option value="20">Faster by 20%</option>
                    <option value="30">Faster by 30%</option>
                    <option value="40">Faster by 40%</option>
                    <option value="50">Faster by 50%</option>
                  </select>
                </div>
                <div className="field">
                  <label>Change Pitch:</label>
                  <select name="mix-pitch">
                    <option value="">No change</option>
                    <option value="separator-1">---------------</option>
                    <option value="-1">Down 1 Semitone</option>
                    <option value="-2">Down 2 Semitones</option>
                    <option value="-3">Down 3 Semitones</option>
                    <option value="-4">Down 4 Semitones</option>
                    <option value="-5">Down 5 Semitones</option>
                    <option value="-6">Down 6 Semitones</option>
                    <option value="-7">Down 7 Semitones</option>
                    <option value="-8">Down 8 Semitones</option>
                    <option value="-9">Down 9 Semitones</option>
                    <option value="-10">Down 10 Semitones</option>
                    <option value="-11">Down 11 Semitones</option>
                    <option value="-12">Down 12 Semitones</option>
                    <option value="separator-2">---------------</option>
                    <option value="1">Up 1 Semitone</option>
                    <option value="2">Up 2 Semitones</option>
                    <option value="3">Up 3 Semitones</option>
                    <option value="4">Up 4 Semitones</option>
                    <option value="5">Up 5 Semitones</option>
                    <option value="6">Up 6 Semitones</option>
                    <option value="7">Up 7 Semitones</option>
                    <option value="8">Up 8 Semitones</option>
                    <option value="9">Up 9 Semitones</option>
                    <option value="10">Up 10 Semitones</option>
                    <option value="11">Up 11 Semitones</option>
                    <option value="12">Up 12 Semitones</option>
                  </select>
                </div>
                <div className={classNames(nameClassData)}>
                  <label>Mix Name:</label>
                  <input type="text" name="mix-name"/>
                </div>
                <div className="field">
                  <a className={createMixClasses} onClick={this.createMix}>CREATE MIX</a>
                  {errorHtml}
                </div>
                <div className="clearall"/>

              </div>`
          else

            mixControls =
              `<div key="no-full-mix-open" className="create-mix not-active">
                <p>To create a custom mix, you must open the Full JamTrack in the My Mixes section above.</p>
              </div>`

        if @state.showMyMixes
          showMyMixesText = `<a onClick={this.toggleMyMixes}>hide my mixes <div className="details-arrow arrow-up" /></a>`
        else
          showMyMixesText = `<a onClick={this.toggleMyMixes}>show my mixes <div className="details-arrow arrow-down" /></a>`

        if @state.showCustomMixes
          showMixControlsText = `<a onClick={this.toggleCustomMixes}>hide mix controls <div className="details-arrow arrow-up" /></a>`
        else
          showMixControlsText = `<a onClick={this.toggleCustomMixes}>show mix controls <div className="details-arrow arrow-down" /></a>`


        extraControls = `
        <div className="extra-controls">
          <h4>My Mixes {showMyMixesText}</h4>
          <ReactCSSTransitionGroup transitionName="session-track-list" transitionAppear={true}>
          {myMixes}
          </ReactCSSTransitionGroup>
          <h4 className="custom-mix-header">Create Custom Mix {showMixControlsText}</h4>
          <ReactCSSTransitionGroup transitionName="session-track-list" transitionAppear={true}>
          {mixControls}
          </ReactCSSTransitionGroup>
        </div>`
      else

        mediaType = "JamTrack"
        mediaName = @state.media.jamTrackName
        closeLinkText = 'CLOSE JAMTRACK'

        # implies we have a mixdown
        if @state.media.jamTrackMixdown.id?
          jamTrackTypeHeader = 'Custom Mix'
        else
          jamTrackTypeHeader = 'Full JamTrack'

        header = `
          <div className="header">
            <h3>{mediaType}: {mediaName}</h3>
            <h4>{jamTrackTypeHeader}</h4>
            {customMixName}
          </div>`



    else if @state.media.mediaSummary.backingTrackOpen
      mediaType = "Audio File"
      mediaName = context.JK.getNameOfFile(@state.media.backingTracks[0].shortFilename)
      closeLinkText = 'CLOSE AUDIO FILE'
      header = `<h3>{mediaType}: {mediaName}</h3>`
      extraControls =
      `<div>
        <div className="field">
          <input type="checkbox" name="loop" /><label htmlFor="loop">Loop audio file playback</label>
        </div>
        <br className="clearall"/>
      </div>`
    else if @state.media.mediaSummary.metronomeOpen
      mediaType = "Metronome"
      closeLinkText = 'CLOSE METRONOME'
      header = `<h3>Metronome</h3>`
      extraControls =
      `<div>
        <a className="display-metronome" onClick={this.showMetronome}>Display visual metronome</a>
      </div>`
    else
      mediaType = ""

    if helpLink?
      helpButton = `<a className="help-link button-grey" href={helpLink} onClick={this.help}>HELP</a>`

    if @state.media.mediaSummary.isOpener || @state.media.mediaSummary.metronomeOpen
      enabledClass = 'close-link button-orange'
    else
      enabledClass = 'close-link button-grey'
      closeLinkText = 'ONLY OPENER CAN CLOSE'

    `<div className="media-controls-popup">
      {header}
      <MediaControls unloaded={this.unloaded} disabled={this.state.downloadingJamTrack || this.disableLoading}/>
      {extraControls}
      <div className="actions">
        {helpButton}
        <a className={enabledClass} onClick={this.close}>{closeLinkText}</a>
      </div>
    </div>`


  windowUnloaded: (event) ->
    logger.debug('PopupMediaControls: window uploaded')
    SessionActions.log({msg: 'PopupMediaControls: window uploaded', event: event})
    @unloaded = true
    window.unloaded = true

    @props.windowUnloaded()

    MixerActions.closeMedia(false) unless window.DontAutoCloseMedia

  toggleMyMixes: (e) ->
    e.preventDefault()
    @setState({showMyMixes: !@state.showMyMixes})

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

    @setState({showCustomMixes: !@state.showCustomMixes})

  mixdownPlay: (mixdown, e) ->
    @setState({editingMixdownId: null})

    e.preventDefault()

    if @disableLoading
      alert('Certain actions are disabled while a track is being loaded.')
      return

    # make this package the active one
    JamTrackMixdownActions.openMixdown(mixdown)

  jamTrackPlay: (jamtrack, e) ->
    e.preventDefault()
    # user wants to select the full track

    if @disableLoading
      alert('Certain actions are disabled while a track is being loaded.')
      return

    JamTrackActions.activateNoMixdown(jamtrack)

  verificationCheck: () ->
    if @state.user?.email_needs_verification
      alert("Check your email and click the verification link.  Close and re-open this JamTrack, and try again.")

    return @state.user?.email_needs_verification

  jamTrackDownload: (jamTrack, e) ->
    e.preventDefault()

    return if @verificationCheck()

    if !@state.jamTrackState.jamTrack.can_download
      e.preventDefault()
      if confirm("You have not purchased the rights to download a JamTrack. Add them to your shopping cart?")
        @addUpgradeToCart(@state.jamTrackState.jamTrack)
      return

    new window.Fingerprint2().get((result, components) => (
      redirectTo = "/api/jamtracks/#{jamTrack.id}/stems/master/download.mp3?file_type=mp3&download=1&mark=#{result}"
      redirectTo = encodeURIComponent(redirectTo)
      AppActions.openExternalUrl(window.location.protocol + '//' + window.location.host + "/signin?redirect-to=#{redirectTo}")
    ))

  addUpgradeToCart: (jamtrack) ->
    console.log("adding upgrade to cart")

    params = {id: jamtrack.id, variant: 'download'}

    rest.addJamtrackToShoppingCart(params).done((response) =>
      console.log("added item to shopping cart.  fast_redeem? " + response.fast_redeem)
      if response.fast_reedem
        if context.JK.currentUserId?
          AppActions.openExternalUrl(window.location.protocol + '//' + window.location.host + '/client#/redeemComplete')
        else
          AppActions.openExternalUrl(window.location.protocol + '//' + window.location.host + '/client#/redeemSignup')
      else
        AppActions.openExternalUrl(window.location.protocol + '//' + window.location.host +  '/client#/shoppingCart')

    ).fail(((jqxhr) =>

        handled = false
        if jqxhr.status == 422
          body = JSON.parse(jqxhr.responseText)
          if body.errors?.cart_id?[0] == 'has already been taken'
            console.log("already taken, just show shopping cart")
            AppActions.openExternalUrl(window.location.protocol + '//' + window.location.host + '/client#/shoppingCart')
            return
          else if body.errors && body.errors.base
            handled = true
            alert("You can not have a mix of free and non-free items in your shopping cart.\n\nIf you want to add this new item to your shopping cart, then clear out all current items by clicking on the shopping cart icon and clicking 'delete' next to each item.")
        if !handled
          alert("Error adding to shoppig cart. " + jqxhr.responseText)
      ))

  stemChanged:() ->
  stemDownload: (e) ->
    e.preventDefault()

    return if @verificationCheck()

    $select = $(this.getDOMNode()).find('.active-stem-select')

    if !@state.jamTrackState.jamTrack.can_download
      e.preventDefault()
      if confirm("You have not purchased the rights to download a JamTrack. Add them to your shopping cart?")
        @addUpgradeToCart(@state.jamTrackState.jamTrack)
      return

    selectedTrackId = $select.val()

    if !selectedTrackId? || selectedTrackId == ''
      alert("You must select a track in order to download.")
    else
      e.preventDefault()

      new window.Fingerprint2().get((result, components) => (
        redirectTo = "/api/jamtracks/#{@state.jamTrackState.jamTrack.id}/stems/#{selectedTrackId}/download.mp3?file_type=mp3&download=1&mark=#{result}"
        redirectTo = encodeURIComponent(redirectTo)
        AppActions.openExternalUrl(window.location.protocol + '//' + window.location.host + "/signin?redirect-to=#{redirectTo}")
      ))


  onEditKeydown: (mixdown, e) ->
    logger.debug("on edit keydown", e)
    if e.keyCode == 13 # enter
      @mixdownSave(mixdown, e)
    else if e.keyCode == 27 # esc
      @setState({editingMixdownId: null})

  mixdownEdit: (mixdown) ->
    @setState({editingMixdownId: mixdown.id})

  mixdownSave: (mixdown, e) ->
    e.preventDefault()
    $input = $(this.getDOMNode()).find('input.edit-name')
    newValue = $input.val()
    logger.debug("editing mixdown name to be: " + newValue)
    JamTrackMixdownActions.editMixdown({id: mixdown.id, name: newValue})
    @setState({editingMixdownId: null})

  mixdownDelete: (mixdown) ->
    if @state.editingMixdownId?
      @setState({editingMixdownId:null})
      return

    if confirm("Delete this custom mix?")
      JamTrackMixdownActions.deleteMixdown(mixdown)

  downloadMixdownReady: (mixdown, e) ->
    e.preventDefault()

    return if @verificationCheck()

    # find the mp3 package for browser state check
    for mixdown_package in mixdown.packages
      if mixdown_package.file_type == 'mp3'
        browserPackage = mixdown_package
        break

    if browserPackage?.signing_state == 'SIGNED'
      new window.Fingerprint2().get((result, components) => (
        redirectTo = "/api/mixdowns/#{mixdown.id}/download.mp3?file_type=mp3&sample_rate=48&download=1&mark=#{result}"
        redirectTo = encodeURIComponent(redirectTo)
        AppActions.openExternalUrl(window.location.protocol + '//' + window.location.host + "/signin?redirect-to=#{redirectTo}")
      ))
    else
      JamTrackMixdownActions.openDownloader(mixdown)

  mixdownError: (mixdown) ->

    myPackage = mixdown.myPackage

    if myPackage?
      switch myPackage.signing_state
        when 'QUIET_TIMEOUT'
          action = 'Custom mix never got created.  Retry?'
        when 'QUEUED_TIMEOUT'
          action = 'Custom mix was never built. Retry?'
        when 'SIGNING_TIMEOUT'
          action = 'Custom mix took took long to build.  Retry?'
        when 'ERROR'
          action = 'Custom mix failed to build. Retry?'
    else
      action = 'Custom mix never got created. Retry?'

    return unless action?

    if confirm(action)
      JamTrackMixdownActions.enqueueMixdown(mixdown, @enqueueDone)

  enqueueDone: (enqueued) ->
    @promptEstimate(enqueued)

  promptEstimate: (enqueued) ->
    time = enqueued.queue_time

    if time == 0
      alert("Your custom mix will take about 1 minute to be created.")
    else
      guess = Math.ceil(time / 60.0)
      if guess == 1
        msg = '1 minute'
      else
        msg = "#{guess} minutes"
      alert("Your custom mix will take about #{msg} to be created.")


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

    return if @state.creatingMix

    $root = $(@getDOMNode())

    name = $root.find('input[name="mix-name"]').val()
    speed = $root.find('select[name="mix-speed"]').val()
    pitch = $root.find('select[name="mix-pitch"]').val()

    if @state.jamTrackState.jamTrack?.activeMixdown?
      @setState({createMixdownErrors: {errors: {'Full JamTrack': ['must be selected']}}})
      return

    if name == null || name == ''
      @setState({createMixdownErrors: {errors: {'Mix Name': ["can't be blank"]}}})
      return

    # sanitize junk out of speed/pitch
    if speed == '' || speed.indexOf('separator') > -1
      speed = undefined
    else
      speed = parseInt(speed)
    if pitch == '' || pitch.indexOf('separator') > -1
      pitch = undefined
    else
      pitch = parseInt(pitch)

    mixdown = {jamTrackID: @state.jamTrackState.jamTrack.id, name: name, settings: {speed:speed, pitch: pitch}}

    JamTrackMixdownActions.createMixdown(mixdown, @createMixdownDone, @createMixdownFail)

    @setState({creatingMixdown: true, createMixdownErrors: null})

  createMixdownDone: (created) ->
    logger.debug("created (within PopupMediaControls)", created)
    # automatically close the create custom mix area
    @setState({creatingMixdown: false, showCustomMixes: false, showMyMixes: true})

    @promptEstimate(created)

  createMixdownFail: (jqXHR) ->
    logger.debug("create mixdown fail (within PopupMediaControls)", jqXHR.status)
    @setState({creatingMixdown: false})
    if jqXHR.status == 422
      response = JSON.parse(jqXHR.responseText)
      logger.warn("failed to create mixdown", response, jqXHR.responseText)

    @setState({createMixdownErrors: response})


  componentDidMount: () ->

    $(window).unload(@windowUnloaded)

    $(window).on('beforeunload', (event) =>
      # Cancel the event as stated by the standard.
      #event.preventDefault()
      #Chrome requires returnValue to be set.
      #event.returnValue = ''
      #SessionActions.log({msg:"beforeunload", event: event})
    )

    @root = jQuery(this.getDOMNode())

    $loop = @root.find('input[name="loop"]')
    context.JK.checkbox($loop)

    $loop.on('ifChecked', () =>
      # it doesn't matter if you do personal or master, because backend just syncs both
      MixerActions.loopChanged(@state.media.backingTracks[0].mixers.personal.mixer, true)
    )
    $loop.on('ifUnchecked', () =>
      # it doesn't matter if you do personal or master, because backend just syncs both
      MixerActions.loopChanged(@state.media.backingTracks[0].mixers.personal.mixer, false)
    )

    @resizeWindow()

    # this is necessary due to whatever the client's rendering behavior is.
    setTimeout(@resizeWindow, 300)

  componentDidUpdate: () ->
    @resizeWindow()
    setTimeout(@resizeWindow, 1000)

  shouldComponentUpdate: () ->
    return !@unloaded

  resizeWindow: () =>
    $container = $('#minimal-container')
    width = $container.width()
    height = $container.height()

    # there is 20px or so of unused space at the top of the page.   can't figure out why it's there. (above #minimal-container)
    #mysteryTopMargin = 20
    mysteryTopMargin = 0
    # deal with chrome in real browsers
    offset = (window.outerHeight - window.innerHeight) + mysteryTopMargin

    # handle native client chrome that the above outer-inner doesn't catch
    #if navigator.userAgent.indexOf('JamKazam') > -1

    #offset += 25

    window.resizeTo(width, height + offset)

  computeDisableLoading: (state) ->
    @disableLoading = false

    return unless nextState?

    selectedMixdown = state?.jamTrackState?.jamTrack?.activeMixdown

    mixdownDownloading = false
    if selectedMixdown?
      switch selectedMixdown.client_state
        when 'keying'
          mixdownDownloading = true
        when 'downloading'
          mixdownDownloading = true


    @disableLoading = SessionStore.downloadingJamTrack || mixdownDownloading

  componentWillMount: () ->
    @computeDisableLoading(@state)

  componentWillUpdate: (nextProps, nextState) ->
    @computeDisableLoading(nextState)


})