$ = jQuery
context = window
context.JK ||= {}

context.JK.JamTrackScreen=class JamTrackScreen
  LIMIT = 10
  instrument_logo_map = context.JK.getInstrumentIconMap24()

  constructor: (@app) ->
    @EVENTS = context.JK.EVENTS
    @logger = context.JK.logger
    @screen = null
    @content = null
    @scroller = null
    @genre = null
    @artist = null
    @instrument = null
    @availability = null
    @nextPager = null
    @noMoreJamtracks = null
    @currentPage = 0
    @next = null
    @currentQuery = this.defaultQuery()
    @expanded = null
    @shownHelperBubbles = false
    
  beforeShow:(data) =>
    this.setFilterFromURL()

    if context.JK.currentUserId?
      @app.user().done((user) =>
        @user = user
        this.refresh()
      ).fail((arg) =>
        @logger.error("app.user.done failed: " + JSON.stringify(arg))

        @logger.debug(arg.statusCode);

        throw 'fail should not occur if user is available'
      )
    else
      this.refresh()
      unless @shownHelperBubbles
        @shownHelperBubbles = true
        @startHelperBubbles()

  afterShow:(data) =>
    context.JK.Tracking.jamtrackBrowseTrack(@app)

  beforeHide: () =>
    this.clearCtaHelpTimeout()
    this.clearBandFilterHelpTimeout()
    this.clearMasterHelpTimeout()
    this.clearResults();

  events:() =>
    @genre.on 'change', this.search
    @artist.on 'change', this.search
    @instrument.on 'change', this.search
    @availability.on 'change', this.search

  clearResults:() =>
    @currentPage = 0
    @content.empty()
    @noMoreJamtracks.hide()
    @next = null

  startHelperBubbles: () =>
    @showBandFilterHelpTimeout = setTimeout(@showBandFilterHelp, 3500)

  showBandFilterHelp: () =>
    context.JK.HelpBubbleHelper.jamtrackBrowseBand(@artist.closest('.easydropdown-wrapper'), $('body'))

    @showMasterHelpDueTime = new Date().getTime() + 11000 # 6000 ms for band tooltip to display, and 5 seconds of quiet time
    @scroller.on('scroll', @masterHelpScrollWatch)
    @scroller.on('scroll', @clearBubbles)
    @showMasterHelpTimeout = setTimeout(@showMasterHelp, @masterHelpDueTime())

  clearBubbles: () =>
    if @helpBubble?
      @helpBubble.btOff()
      @helpBubble = null

  # computes when we should show the master help bubble
  masterHelpDueTime: () =>
    dueTime = @showMasterHelpDueTime - new Date().getTime()
    if dueTime <= 0
      dueTime = 2000
    dueTime


  # computes when we should show the master help bubble
  ctaHelpDueTime: () =>
    dueTime = @showCtaHelpDueTime - new Date().getTime()
    if dueTime <= 0
      dueTime = 2000
    dueTime

  # if the user scrolls, reset the master help due time
  masterHelpScrollWatch: () =>
    @clearMasterHelpTimeout()
    @showMasterHelpTimeout = setTimeout(@showMasterHelp, @masterHelpDueTime() + 2000)

  # if the user scrolls, reset the master help due time
  ctaHelpScrollWatch: () =>
    @clearCtaHelpTimeout()
    @showCtaHelpTimeout = setTimeout(@showCtaHelp, @ctaHelpDueTime() + 2000)


  showCtaHelp: () =>
    @scroller.off('scroll', @ctaHelpScrollWatch)
    @clearCtaHelpTimeout()

    cutoff = @scroller.offset().top;

    @screen.find('.jamtrack-actions').each((i, element) =>
      $element = $(element)

      if ($element.offset().top >= cutoff)
        @helpBubble = context.JK.HelpBubbleHelper.jamtrackBrowseCta($element, $('body'))
        return false
      else
        return true
    )

  showMasterHelp: () =>
    @scroller.off('scroll', @masterHelpScrollWatch)
    @clearMasterHelpTimeout()

    # don't show the help  if the user has already clicked a preview
    unless @userPreviewed
      cutoff = @scroller.offset().top;

      @screen.find('.jamtrack-preview[data-track-type="Master"]').each((i, element) =>
        $element = $(element)

        if ($element.offset().top >= cutoff)
          @helpBubble = context.JK.HelpBubbleHelper.jamtrackBrowseMasterMix($element.find('.play-button'), $('body'))
          return false
        else
          return true
      )

    @showCtaHelpDueTime = new Date().getTime() + 11000
    @scroller.on('scroll', @ctaHelpScrollWatch)
    @showCtaHelpTimeout = setTimeout(@showCtaHelp, @ctaHelpDueTime()) # 6000 ms for bubble show time, and 5000ms for delay

  previewPlayed: () =>
    @userPreviewed = true

  clearCtaHelpTimeout:() =>
    if @showCtaHelpTimeout?
      clearTimeout(@showCtaHelpTimeout)
      @showCtaHelpTimeout = null

  clearBandFilterHelpTimeout: () =>
    if @showBandFilterHelpTimeout?
      clearTimeout(@showBandFilterHelpTimeout)
      @showBandFilterHelpTimeout = null

  clearMasterHelpTimeout: () =>
    if @showMasterHelpTimeout?
      clearTimeout(@showMasterHelpTimeout)
      @showMasterHelpTimeout = null

  setFilterFromURL:() =>
    # Grab parms from URL for artist, instrument, and availability
    parms=this.getParams()
    
    if(parms.artist?)
      @artist.val(parms.artist)
    else
      @artist.val('')
    if(parms.instrument?)
      @instrument.val(parms.instrument)
    else
      @instrument.val('')
    if(parms.availability?)
      @availability.val(parms.availability)
    else
      @availability.val('')

    if window.history.replaceState #ie9 proofing
      window.history.replaceState({}, "", "/client#/jamtrackBrowse")
    
  getParams:() =>
    params = {}      
    q = window.location.href.split("?")[1]
    if q?
      q = q.split('#')[0]
      raw_vars = q.split("&")
      for v in raw_vars
        [key, val] = v.split("=")
        params[key] = decodeURIComponent(val)
    params

  setFilterState: (state) =>
    if state
      @genre.easyDropDown('enable').removeAttr('disabled')
      @artist.easyDropDown('enable').removeAttr('disabled')
      @instrument.easyDropDown('enable').removeAttr('disabled')
      @availability.easyDropDown('enable').removeAttr('disabled')
    else
      @genre.easyDropDown('disable').attr('disabled', 'disabled')
      @artist.easyDropDown('disable').attr('disabled', 'disabled')
      @instrument.easyDropDown('disable').attr('disabled', 'disabled')
      @availability.easyDropDown('disable').attr('disabled', 'disabled')

  refresh:() =>
    this.clearResults()
    @currentQuery = this.buildQuery()
    that = this
    this.setFilterState(false)
    rest.getJamTracks(@currentQuery).done((response) =>
      that.handleJamtrackResponse(response)
    ).fail( (jqXHR) =>
      that.clearResults()
      that.noMoreJamtracks.show()
      that.app.notifyServerError jqXHR, 'Jamtrack Unavailable'
    ).always () =>
      that.setFilterState(true)

  search:() =>
    this.refresh()
    false

  defaultQuery:() =>
    query =
      per_page: LIMIT
      page: @currentPage+1
    if @next
      query.since = @next
    query

  buildQuery:() => 
    @currentQuery = this.defaultQuery()
    # genre filter
    # var genres = @screen.find('#jamtrack_genre').val()
    # if (genres !== undefined) {
    #   @currentQuery.genre = genres
    # }
    # instrument filter
    
    instrument = @instrument.val()
    if instrument?
      @currentQuery.instrument = instrument

    # artist filter
    art = @artist.val()
    if art?
      @currentQuery.artist = art
    
    # availability filter
    availability = @availability.val()
    if availability?
      @currentQuery.availability = availability
    @currentQuery

  handleJamtrackResponse:(response) =>
    @next = response.next
    this.renderJamtracks(response)
    if response.next == null
      # if we less results than asked for, end searching
      @scroller.infinitescroll 'pause'
      if @currentPage == 0 and response.jamtracks.length == 0
        @content.append '<td colspan="3" class="no-jamtracks-msg\'>No JamTracks found.</div>'
      if @currentPage > 0
        @noMoreJamtracks.show()
        # there are bugs with infinitescroll not removing the 'loading'.
        # it's most noticeable at the end of the list, so whack all such entries
        $('.infinite-scroll-loader').remove()
    else
      @currentPage++
      this.buildQuery()
      this.registerInfiniteScroll()


  registerInfiniteScroll:() =>
    that = this
    @scroller.infinitescroll {
      behavior: 'local'
      navSelector: '#jamtrackScreen .btn-next-pager'
      nextSelector: '#jamtrackScreen .btn-next-pager'
      binder: @scroller
      dataType: 'json'
      appendCallback: false
      prefill: false
      bufferPx: 100
      loading:
        msg: $('<div class="infinite-scroll-loader">Loading ...</div>')
        img: '/assets/shared/spinner.gif'
      path: (page) =>
        '/api/jamtracks?' + $.param(that.buildQuery())

    }, (json, opts) =>
      this.handleJamtrackResponse(json)
    @scroller.infinitescroll 'resume'    

  playJamtrack:(e) =>
    e.preventDefault()    

  addToCartJamtrack:(e) =>
    e.preventDefault()
    $target = $(e.target)
    params = id: $target.attr('data-jamtrack-id')
    isFree = $(e.target).is('.is_free')

    rest.addJamtrackToShoppingCart(params).done((response) =>
      if(isFree)
        if context.JK.currentUserId?
          alert("TODO")
          context.JK.currentUserFreeJamTrack = true # make sure the user sees no more free notices
          context.location = '/client#/redeemComplete'
        else
          # now make a rest call to buy it
          context.location = '/client#/redeemSignup'

      else
        context.location = '/client#/shoppingCart'

    ).fail @app.ajaxError    

  licenseUSWhy:(e) =>
    e.preventDefault()
    @app.layout.showDialog 'jamtrack-availability-dialog'

  handleExpanded:(trackElement) =>
    jamTrack = trackElement.data('jamTrack')
    expanded = trackElement.data('expanded')
    expand = !expanded
    trackElement.data('expanded', expand)

    detailArrow = trackElement.find('.jamtrack-detail-btn')

    if expand
      trackElement.find('.extra').removeClass('hidden')
      detailArrow.html('hide tracks <a class="details-arrow arrow-up"></a>')
      for track in jamTrack.tracks
        trackElement.find("[jamtrack-track-id='#{track.id}']").removeClass('hidden')
    else
      trackElement.find('.extra').addClass('hidden')
      detailArrow.html('show all tracks <a class="details-arrow arrow-down"></a>')
      count = 0
      for track in jamTrack.tracks
        if count < 6
          trackElement.find("[jamtrack-track-id='#{track.id}']").removeClass('hidden')
        else
          trackElement.find("[jamtrack-track-id='#{track.id}']").addClass('hidden')
        count++


  registerEvents:(parent) =>
    #@screen.find('.jamtrack-detail-btn').on 'click', this.showJamtrackDescription
    parent.find('.play-button').on 'click', this.playJamtrack
    parent.find('.jamtrack-add-cart').on 'click', this.addToCartJamtrack
    parent.find('.license-us-why').on 'click', this.licenseUSWhy
    parent.find('.jamtrack-detail-btn').on 'click', this.toggleExpanded
    # @screen.find('.jamtrack-preview').each (index, element) =>
    #   new JK.JamTrackPreview(data.app, $element, jamTrack, track, {master_shows_duration: true})
  
  rerenderJamtracks:() => 
    if @currentData?      
      @clearResults()
      @renderJamtracks(@currentData) 
    false

  computeWeight: (jam_track_track, instrument) =>
    weight = switch
      when jam_track_track.track_type == 'Master' then 0
      when jam_track_track.instrument?.id == instrument then 1 + jam_track_track.position
      else 10000 + jam_track_track.position

  renderJamtracks:(data) =>
    @currentData = data
    that = this

    for jamtrack in data.jamtracks
      jamtrackExpanded = this.expanded==jamtrack.id
      trackRow = _.clone(jamtrack)
      trackRow.track_cnt = jamtrack.tracks.length
      trackRow.tracks = []

      # if an instrument is selected by the user, then re-order any jam tracks with a matching instrument to the top
      instrument = @instrument.val()
      if instrument?
        jamtrack.tracks.sort((a, b) =>
          aWeight = @computeWeight(a, instrument)
          bWeight = @computeWeight(b, instrument)
          return aWeight - bWeight
        )

      for track in jamtrack.tracks
        trackRow.tracks.push(track)
        if track.track_type=='Master'
          track.instrument_desc = "Master"
        else
          inst = '../assets/content/icon_instrument_default24.png'
          if track.instrument?
            if track.instrument.id in instrument_logo_map
              inst = instrument_logo_map[track.instrument.id].asset
            track.instrument_desc = track.instrument.description
          track.instrument_url = inst

          if track.part != ''
            track.instrument_desc += ' (' + track.part + ')'

      free_state = if context.JK.currentUserFreeJamTrack then 'free' else 'non-free'

      is_free = free_state == 'free'

      options = 
        jamtrack: trackRow
        expanded: false
        free_state: free_state,
        is_free: is_free
      @jamtrackItem = $(context._.template($('#template-jamtrack').html(), options, variable: 'data'))
      that.renderJamtrack(@jamtrackItem, jamtrack)
      that.registerEvents(@jamtrackItem)


  renderJamtrack:(jamtrackElement, jamTrack) =>
    jamtrackElement.data('jamTrack', jamTrack)
    jamtrackElement.data('expanded', true)

    @content.append jamtrackElement    
    
    #if this.expanded==jamTrack.id
    for track in jamTrack.tracks
      trackRow = jamtrackElement.find("[jamtrack-track-id='#{track.id}']")
      previewElement = trackRow.find(".jamtrack-preview")
      preview = new JK.JamTrackPreview(@app, previewElement, jamTrack, track, {master_shows_duration: true, color:'gray'})
      $(preview).on(@EVENTS.PREVIEW_PLAYED, @previewPlayed)

    this.handleExpanded(jamtrackElement, false)

  showJamtrackDescription:(e) =>
    e.preventDefault()
    @description = $(e.target).parent('.detail-arrow').next()
    if @description.css('display') == 'none'
      @description.show()
    else
      @description.hide()    

  toggleExpanded:(e) =>
    e.preventDefault() 
    jamtrackRecord = $(e.target).parents('.jamtrack-record')
    jamTrackId = jamtrackRecord.attr("jamtrack-id")

    this.handleExpanded(jamtrackRecord)
    
  initialize:() =>
    screenBindings =
      'beforeShow': this.beforeShow
      'afterShow': this.afterShow
      'beforeHide' : this.beforeHide
    @app.bindScreen 'jamtrackBrowse', screenBindings
    @screen = $('#jamtrack-find-form')
    @scroller = @screen.find('.content-body-scroller')
    @content = @screen.find('.jamtrack-content')
    @genre = @screen.find('#jamtrack_genre')
    @artist = @screen.find('#jamtrack_artist')
    @instrument = @screen.find('#jamtrack_instrument')
    @availability = @screen.find('#jamtrack_availability')
    @nextPager = @screen.find('a.btn-next-pager')
    @noMoreJamtracks = @screen.find('.end-of-jamtrack-list')
    if @screen.length == 0
      throw new Error('@screen must be specified')
    if @scroller.length == 0
      throw new Error('@scroller must be specified')
    if @content.length == 0
      throw new Error('@content must be specified')
    if @noMoreJamtracks.length == 0
      throw new Error('@noMoreJamtracks must be specified')
    #if(@genre.length == 0) throw new Error("@genre must be specified")

    if @artist.length == 0
      throw new Error('@artist must be specified')
    if @instrument.length == 0
      throw new Error('@instrument must be specified')
    #if @availability.length == 0
    #  throw new Error('@availability must be specified')
    this.events()
    

