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

context.JK.BaseSearchFilter = class BaseSearchFilter

  constructor: () ->
    @rest = context.JK.Rest()
    @logger = context.JK.logger
    @searchFilter = null
    @profileUtils = context.JK.ProfileUtils
    @helpBubble = context.JK.HelpBubbleHelper
    @searchResults = null
    @isSearching = false
    @pageNumber = 1
    @instrument_logo_map = context.JK.getInstrumentIconMap24()
    @searchType = ''
    @searchTypeS = ''
    @restGet = null
    @restPost = null
    @searchMeta = null

  init: (app) =>
    @app = app
    @screenBindings = { 'afterShow': this.afterShow, 'afterHide': this.afterHide }
    @app.bindScreen(@searchTypeS, @screenBindings)

    @screen = $('#'+@searchTypeS+'-screen')
    @resultsListContainer = @screen.find('#'+@searchType+'-search-filter-results-list')
    @spinner = @screen.find('.paginate-wait')

    this.registerResultsPagination()

  afterShow: () =>    
    @screen.find('#'+@searchType+'-search-filter-results').show()
    @screen.find('#'+@searchType+'-search-filter-builder').hide()
    this.getUserFilterResults()

  showBuilder: () =>
    @screen.find('#'+@searchType+'-search-filter-results').hide()
    @screen.find('#'+@searchType+'-search-filter-builder').show()
    @resultsListContainer.empty()

  afterHide: () =>
    @resultsListContainer.empty()

  searchMetaData: () =>
    @searchMeta

  filterData: () =>
    @searchFilter.data_blob

  renderSearchFilter: () => 
    $.when(@restGet()).done (sFilter) =>
      this.loadSearchFilter(sFilter)

  loadSearchFilter: (sFilter) =>

  _populateSelectWithKeys: (struct, selection, keys, element) =>
    element.children().remove()
    $.each keys, (idx, value) =>
      label = struct[value]
      blankOption = $ '<option value=""></option>'
      blankOption.text label
      blankOption.attr 'value', value
      blankOption.attr 'selected', '' if value == selection
      element.append(blankOption)
    context.JK.dropdown(element)

  _populateSelectIdentifier: (identifier) =>
    elem = $ '#'+@searchType+'-search-filter-builder select[name='+identifier+']'
    struct = this.searchMetaData()[identifier]['map']
    keys = this.searchMetaData()[identifier]['keys']
    this._populateSelectWithKeys(struct, this.filterData()[identifier], keys, elem)

  _populateSelectWithInt: (sourceStruct, selection, element) =>
    struct = 
      '-1': 'Any'
    $.extend(struct, sourceStruct)
    this._populateSelectWithKeys(struct, selection, Object.keys(struct).sort(), element)

  _populateSortOrder: () =>
    this._populateSelectIdentifier('sort_order')

  _populateGigs: () => 
    elem = $ '#'+@searchType+'-search-filter-builder select[name=concert_gigs]'
    this._populateSelectWithInt(@profileUtils.gigMap, this.filterData().concert_gigs.toString(), elem)

  _populateGenres: () =>
    @screen.find('#search-filter-genres').empty()
    @rest.getGenres().done (genres) =>
      genreTemplate = @screen.find('#template-search-filter-setup-genres').html()
      filterGenres = this.filterData().genres
      $.each genres, (index, genre) =>
        if 0 < filterGenres.length 
          genreMatch = $.grep(filterGenres, (n, i) ->
            n == genre.id) 
        else 
          genreMatch = []    
        if genreMatch.length > 0 then selected = 'checked' else selected = ''
        genreHtml = context.JK.fillTemplate(genreTemplate,
          id: genre.id
          description: genre.description
          checked: selected)
        @screen.find('#search-filter-genres').append genreHtml
  
  _populateInstruments: () =>
    @screen.find('#search-filter-instruments').empty()
    @rest.getInstruments().done (instruments) =>
      $.each instruments, (index, instrument) =>
        instrumentTemplate = @screen.find('#template-search-filter-setup-instrument').html()
        selected = ''
        proficiency = '1'
        if 0 < this.filterData().instruments.length
          instMatch = $.grep(this.filterData().instruments, (inst, i) ->
            yn = inst.instrument_id == instrument.id
            proficiency = inst.proficiency_level if yn
            yn)
          selected = 'checked' if instMatch.length > 0
        instrumentHtml = context.JK.fillTemplate(instrumentTemplate,
          id: instrument.id
          description: instrument.description
          checked: selected)
        @screen.find('#search-filter-instruments').append instrumentHtml
        profsel = '#search-filter-instruments tr[data-instrument-id="'+instrument.id+'"] select'
        jprofsel = @screen.find(profsel)
        jprofsel.val(proficiency)
        context.JK.dropdown(jprofsel)
        return true

  _builderSelectValue: (identifier) =>
    elem = $ '#'+@searchType+'-search-filter-builder select[name='+identifier+']'
    elem.val()

  _builderSelectMultiValue: (identifier) =>
    vals = []
    elem = $ '#search-filter-'+identifier+' input[type=checkbox]:checked'
    if 'instruments' == identifier
      elem.each (idx) ->
        row = $(this).parent().parent()
        instrument =
          instrument_id: row.data('instrument-id')
          proficiency_level: row.find('select').val()
        vals.push instrument
    else
      elem.each (idx) ->
        if $(this).prop('checked')
          vals.push $(this).val()
    vals

  willSearch: (reload) =>
    return false if @isSearching
    @isSearching = true
    if reload 
      @pageNumber = 1
      @screen.find('#'+@searchType+'-search-filter-spinner').show()
      @resultsListContainer.empty()
      @screen.find('#'+@searchType+'-search-filter-builder').hide()
      @screen.find('#'+@searchType+'-search-filter-results').show()
    true
  
  didSearch: (response) =>
    this.loadSearchFilter(response.filter_json)
    @searchResults = response
    @screen.find('#'+@searchType+'-search-filter-spinner').hide()
    this.renderResultsPage()
    @screen.find('.paginate-wait').hide()
    @isSearching = false

  resetFilter: () =>
    if this.willSearch(true)
      @restPost({ filter: 'reset' }).done(this.didSearch)

  cancelFilter: () =>
    this.resetFilter()

  getUserFilterResults: () =>
    if this.willSearch(true)
      this.doRestGet()

  doRestGet: (query) =>
    query2 = 'results=true&'
    unless (typeof query == "undefined")
      query2 += query
    @restGet(query2).done(this.didSearch)

  performSearch: () =>
    if this.willSearch(true)
      $.each this.searchMetaData().filter_keys.single, (index, key) =>
        this.filterData()[key] = this._builderSelectValue(key)
      $.each this.searchMetaData().filter_keys.multi, (index, key) =>
        this.filterData()[key] = this._builderSelectMultiValue(key)
      @restPost({ filter: JSON.stringify(this.filterData()), page: @pageNumber }).done(this.didSearch)

  renderResultsHeader: () =>
    
  renderResultsPage: () =>

  _formatLocation: (band) ->
    if band.city and band.state
      band.city + ', ' + band.state
    else if band.city
      band.city
    else if band.regionname
      band.regionname
    else
      'Location Unavailable'

  friendRequestCallback: (user_id)=> 
    # TODO:

  paginate: () =>
    if @pageNumber < @searchResults.page_count && this.willSearch(false)
      @screen.find('.paginate-wait').show()
      @pageNumber += 1
      @restPost({ filter: JSON.stringify(this.filterData()), page: @pageNumber }).done(this.didSearch)
      return true
    false

  registerResultsPagination: () =>
    _resultsListContainer = @resultsListContainer
    _headerHeight = @screen.find('#'+@searchType+'-search-filter-results-header').height()
    _paginator = this.paginate

    @screen.find('.content-body-scroller').scroll ->
      if _resultsListContainer.is(':visible')
        jthis = $(this)
        wintop = jthis.scrollTop()
        winheight = jthis.innerHeight()
        docheight = jthis[0].scrollHeight - _headerHeight
        scrollTrigger = 0.98;
        if ((wintop / (docheight - winheight)) >= scrollTrigger)
          _paginator()


context.JK.MusicianSearchFilter = class MusicianSearchFilter extends BaseSearchFilter 

  constructor: () ->
    super()
    @searchType = 'musician'
    @searchTypeS = @searchType+'s'
    @restGet = @rest.getMusicianSearchFilter
    @restPost = @rest.postMusicianSearchFilter
    @searchMeta = gon.musician_search_meta

  init: (app) =>
    super(app)
    @screen.find('#btn-'+@searchType+'-search-builder').on 'click', => 
      this.showBuilder()
    @screen.find('#btn-'+@searchType+'-search-reset').on 'click', => 
      this.resetFilter()

  renderSearchFilter: () => 
    super()

  loadSearchFilter: (sFilter) =>
    super(sFilter)

    @searchFilter = JSON.parse(sFilter)                
    args = 
      interests: this.filterData().interests
      skill_level: this.filterData().skill_level
      studio_sessions: this.filterData().studio_sessions
      concert_gigs: this.filterData().concert_gigs

    template = context.JK.fillTemplate(@screen.find('#template-musician-search-filter').html(), args)

    content_root = @screen.find('#musician-search-filter-builder')
    content_root.html template

    @screen.find('#btn-perform-musician-search').on 'click', => 
      this.performSearch()

    @screen.find('#btn-musician-search-cancel').on 'click', => 
      this.cancelFilter()

    this._populateSkill()
    this._populateStudio()
    this._populateGigs()
    this._populateInterests()
    this._populateAges()
    this._populateGenres()
    this._populateInstruments()
    this._populateSortOrder()

  _populateSortOrder: () =>
    this._populateSelectIdentifier('sort_order')

  _populateInterests: () =>
    this._populateSelectIdentifier('interests')

  _populateStudio: () => 
    elem = $ '#musician-search-filter-builder select[name=studio_sessions]'
    this._populateSelectWithInt(@profileUtils.studioMap, this.filterData().studio_sessions.toString(), elem)

  _populateAges: () =>
    @screen.find('#search-filter-ages').empty()
    ages_map = this.searchMetaData()['ages']['map']
    $.each this.searchMetaData()['ages']['keys'], (index, key) =>
      ageTemplate = @screen.find('#template-search-filter-setup-ages').html()
      selected = ''
      ageLabel = ages_map[key]
      if 0 < this.filterData().ages.length
        key_val = key.toString()
        ageMatch = $.grep(this.filterData().ages, (n, i) ->
          n == key_val)
        selected = 'checked' if ageMatch.length > 0
      ageHtml = context.JK.fillTemplate(ageTemplate,
        id: key
        description: ageLabel
        checked: selected)
      @screen.find('#search-filter-ages').append ageHtml

  _populateGenres: () =>
    super()
  
  _populateSkill: () =>
    elem = $ '#'+@searchType+'-search-filter-builder select[name=skill_level]'
    this._populateSelectWithInt(@profileUtils.skillLevelMap, this.filterData().skill_level.toString(), elem)

  _populateInstruments: () =>
    super()

  willSearch: (reload) =>
    super(reload)
  
  didSearch: (response) =>
    super(response)

  resetFilter: () =>
    super()

  cancelFilter: () =>
    super()

  getUserFilterResults: () =>
    super()

  performSearch: () =>
    super()

  renderResultsHeader: () =>
    @screen.find('#'+@searchType+'-search-filter-description').html(@searchResults.description)
    if @searchResults.is_blank_filter
     @screen.find('#btn-'+@searchType+'-search-reset').hide()
    else
     @screen.find('#btn-'+@searchType+'-search-reset').show()
    
  renderResultsPage: () =>
    super()
    this.renderResultsHeader() if @pageNumber == 1
    musicians = @searchResults.musicians
    len = musicians.length
    if 0 == len
      @screen.find('#musician-search-filter-results-list-blank').show()
      @screen.find('#musician-search-filter-results-list-blank').html('No results found')
      return
    else  
      @screen.find('#musician-search-filter-results-list-blank').hide()

    ii = 0
    mTemplate = @screen.find('#template-search-musician-row').html()
    aTemplate = @screen.find('#template-search-musician-action-btns').html()
    mVals = undefined
    musician = undefined
    renderings = ''
    instr_logos = undefined
    follows = undefined
    followVals = undefined
    aFollow = undefined
    myAudioLatency = @searchResults.my_audio_latency
    while ii < len
      musician = musicians[ii]
      if context.JK.currentUserId == musician.id
        ii++
        continue
      instr_logos = ''
      jj = 0
      ilen = musician['instruments'].length
      while jj < ilen
        instr_id = musician['instruments'][jj].instrument_id
        if instr_img = @instrument_logo_map[instr_id]
          instr_logos += '<img height="24" width="24" src="' + instr_img.asset + '" title="' + instr_id + '"/>'
        jj++
      actionVals = 
        profile_url: '/client#/profile/' + musician.id
        friend_class: 'button-' + (if musician['is_friend'] then 'grey' else 'orange')
        friend_caption: (if musician.is_friend then 'DIS' else '') + 'CONNECT'
        follow_class: 'button-' + (if musician['is_following'] then 'grey' else 'orange')
        follow_caption: (if musician.is_following then 'UN' else '') + 'FOLLOW'
        message_class: 'button-orange'
        message_caption: 'MESSAGE'
        button_message: 'button-orange'
      musician_actions = context.JK.fillTemplate(aTemplate, actionVals)
      latencyBadge = context._.template($("#template-account-session-latency").html(), $.extend(sessionUtils.createLatency(musician), musician), variable: 'data')
      mVals =
        avatar_url: context.JK.resolveAvatarUrl(musician.photo_url)
        profile_url: '/client#/profile/' + musician.id
        musician_name: musician.name
        musician_location: this._formatLocation(musician)
        instruments: instr_logos
        biography: musician['biography']
        follow_count: musician['follow_count']
        friend_count: musician['friend_count']
        recording_count: musician['recording_count']
        session_count: musician['session_count']
        musician_id: musician['id']
        musician_action_template: musician_actions
        latency_badge: latencyBadge
        musician_first_name: musician['first_name']
      $rendering = $(context.JK.fillTemplate(mTemplate, mVals))
      $offsetParent = @resultsListContainer.closest('.content')
      data = entity_type: 'musician'
      options = 
        positions: [
          'top'
          'bottom'
          'right'
          'left'
        ]
        offsetParent: $offsetParent
      scoreOptions = offsetParent: $offsetParent
      context.JK.helpBubble($('.follower-count', $rendering), 'follower-count', data, options);
      context.JK.helpBubble($('.friend-count', $rendering), 'friend-count', data, options);
      context.JK.helpBubble($('.recording-count', $rendering), 'recording-count', data, options);
      context.JK.helpBubble($('.session-count', $rendering), 'session-count', data, options);
      @helpBubble.scoreBreakdown $('.latency', $rendering), false, musician['full_score'], myAudioLatency, musician['audio_latency'], musician['score'], scoreOptions
      @resultsListContainer.append $rendering
      $rendering.find('.biography').dotdotdot()
      ii++

    this._bindMessageMusician()
    this._bindFriendMusician()
    this._bindFollowMusician()

    context.JK.bindHoverEvents()
    return  

  _bindMessageMusician: () =>
    objThis = this
    @screen.find('.search-m-message').on 'click', (evt) ->
      userId = $(this).parent().data('musician-id')
      objThis.app.layout.showDialog 'text-message', d1: userId


  _bindFriendMusician: () =>
    objThis = this
    @screen.find('.search-m-friend').on 'click', (evt) ->
      # if the musician is already a friend, remove the button-orange class, and prevent the link from working
      if 0 == $(this).closest('.button-orange').size()
        return false
      $(this).click (ee) ->
        ee.preventDefault()
        return
      evt.stopPropagation()
      uid = $(this).parent().data('musician-id')
      objThis.rest.sendFriendRequest objThis.app, uid, this.friendRequestCallback
  
  _bindFollowMusician: () =>
    objThis = this
    @screen.find('.search-m-follow').on 'click', (evt) ->
      # if the musician is already followed, remove the button-orange class, and prevent the link from working
      if 0 == $(this).closest('.button-orange').size()
        return false
      $(this).click (ee) ->
        ee.preventDefault()
        return
      evt.stopPropagation()
      newFollowing = {}
      newFollowing.user_id = $(this).parent().data('musician-id')
      url = '/api/users/' + context.JK.currentUserId + '/followings'
      $.ajax
        type: 'POST'
        dataType: 'json'
        contentType: 'application/json'
        url: url
        data: JSON.stringify(newFollowing)
        processData: false
        success: (response) ->
          # remove the orange look to indicate it's not selectable
          # @FIXME -- this will need to be tweaked when we allow unfollowing
          objThis.screen.find('div[data-musician-id=' + newFollowing.user_id + '] .search-m-follow').removeClass('button-orange').addClass 'button-grey'
          return
        error: objThis.app.ajaxError
  
  _formatLocation: (musician) ->
    if musician.city and musician.state
      musician.city + ', ' + musician.state
    else if musician.city
      musician.city
    else if musician.regionname
      musician.regionname
    else
      'Location Unavailable'

  friendRequestCallback: (user_id)=> 
    # TODO:

  paginate: () =>
    super()

  registerResultsPagination: () =>
    super()


context.JK.BandSearchFilter = class BandSearchFilter extends BaseSearchFilter 

  constructor: () ->
    super()
    @searchType = 'band'
    @searchTypeS = @searchType+'s'
    @restGet = @rest.getBandSearchFilter
    @restPost = @rest.postBandSearchFilter
    @searchMeta = gon.band_search_meta
    @searchSubType = 'to_join'

  init: (app) =>
    super(app)

    @screen.find('#btn-'+@searchType+'-search-builder-to_join').on 'click', => 
      this.showBuilderToJoin()
    @screen.find('#btn-'+@searchType+'-search-builder-to_hire').on 'click', => 
      this.showBuilderToHire()
    @screen.find('#btn-'+@searchType+'-search-builder').on 'click', => 
      this.showBuilderActive()
    @screen.find('#btn-'+@searchType+'-search-reset').on 'click', => 
      this.resetFilter()

    @resultsList = @screen.find('#band-search-filter-results-list')
    @screen.find('#band-search-filter-results-filtered').hide()

  isToHire: () =>
    'to_hire' == @searchSubType

  showBuilderActive: () =>
    if this.isToHire()
      this.showBuilderToHire()
    else
      this.showBuilderToJoin()

  showBuilderToJoin: () =>
    @screen.find('.band-search-filter-builder-top-to_join').show()
    @screen.find('.band-search-filter-builder-top-to_hire').hide()
    @searchSubType = 'to_join'
    this.showBuilder()
    this._loadSearchFilter() if @searchFilter
    # @screen.find('.band-search-filter-builder-top-to_join h2').html('search bands')

  showBuilderToHire: () =>
    @screen.find('.band-search-filter-builder-top-to_join').hide()
    @screen.find('.band-search-filter-builder-top-to_hire').show()
    @searchSubType = 'to_hire'
    this.showBuilder()
    this._loadSearchFilter() if @searchFilter
    # @screen.find('.band-search-filter-builder-top-to_hire h2').html('search bands to hire')

  searchMetaData: () =>
    @searchMeta[@searchSubType]

  renderSearchFilter: () => 
    super()

  _searchFilterArgsToJoin: () =>
    args = 
      touring_option: this.filterData().touring_option
      band_status: this.filterData().band_status
      play_commitment: this.filterData().play_commitment
      band_type: this.filterData().band_type
      concert_gigs: this.filterData().concert_gigs

  _searchFilterArgsToHire: () =>
    if 0 < this.filterData().max_cost
      has_max_cost = 'checked'
    else
      has_max_cost = ''
    if 1==this.filterData().free_gigs
      has_free_gigs = 'checked'
    else
      has_free_gigs = ''

    args = 
      band_status: this.filterData().band_status
      concert_gigs: this.filterData().concert_gigs
      performance_samples: this.filterData().performance_samples
      has_max_cost: has_max_cost
      max_cost: this.filterData().max_cost
      has_free_gigs: has_free_gigs

  _populateSearchFilterToJoin: () =>
    this._populateInstruments()
    this._populateSkill()
    this._populateGigs()
    this._populatePlayCommit()
    this._populateTourOption()
    this._populateBandStatus()

  _populateSearchFilterToHire: () =>
    this._populateBandStatus()
    this._populateGigs()
    this._populatePerformSamples()

  loadSearchFilter: (sFilter) =>
    super(sFilter)
    @searchFilter = JSON.parse(sFilter)
    this._loadSearchFilter()

  _loadSearchFilter: () =>
    switch @searchSubType
      when 'to_join' then args = this._searchFilterArgsToJoin()
      when 'to_hire' then args = this._searchFilterArgsToHire()

    template = context.JK.fillTemplate(@screen.find('#template-band-search-filter-'+@searchSubType).html(), args)

    content_root = @screen.find('#band-search-filter-builder')
    content_root.html template

    @screen.find('#btn-perform-band-search').on 'click', => 
      this.performSearch()

    @screen.find('#btn-band-search-cancel').on 'click', => 
      this.cancelFilter()

    this._populateGenres()
    this._populateSortOrder() if this.isToHire()

    switch @searchSubType
      when 'to_join' then this._populateSearchFilterToJoin()
      when 'to_hire' then this._populateSearchFilterToHire()

  _populateSkill: () =>
    this._populateSelectIdentifier('band_type')

  _populateBandStatus: () =>
    this._populateSelectIdentifier('band_status')

  _populatePlayCommit: () =>
    this._populateSelectIdentifier('play_commitment')

  _populateTourOption: () =>
    this._populateSelectIdentifier('touring_option')

  _populateSortOrder: () =>
    this._populateSelectIdentifier('sort_order')

  _populatePerformSamples: () =>
    this._populateSelectIdentifier('performance_samples')

  _populateGenres: () =>
    super()
  
  _populateInstruments: () =>
    super()

  willSearch: (reload) =>
    super(reload)
  
  didSearch: (response) =>
    super(response)

  resetFilter: () =>
    if this.willSearch(true)
      @screen.find('#band-search-filter-results-blank').show()
      @screen.find('#band-search-filter-results-filtered').hide()
      @screen.find('#band-search-filter-description').html('')
      @restPost({ filter: 'reset', subtype: @searchSubType }).done(this.didSearch)

  cancelFilter: () =>
    super()

  doRestGet: (query) =>
    super('subtype='+@searchSubType)

  performSearch: () =>
    if this.willSearch(true)
      filterPost = this.filterData()
      $.each this.searchMetaData().filter_keys.single, (index, key) =>
        filterPost[key] = this._builderSelectValue(key)
      $.each this.searchMetaData().filter_keys.multi, (index, key) =>
        filterPost[key] = this._builderSelectMultiValue(key)

      if this.isToHire()
        filterPost['max_cost'] = parseInt($('#max_cost_amount').val())
        filterPost['free_gigs'] = if $('#free_gigs').prop('checked') then 1 else 0
        
      postData = { subtype: @searchSubType, filter: JSON.stringify(filterPost), page: @pageNumber }
      @restPost(postData).done(this.didSearch)

  renderResultsHeader: () =>
    if @searchResults.is_blank_filter
      @screen.find('#band-search-filter-results-blank').show()
      @screen.find('#band-search-filter-results-filtered').hide()
    else
      @screen.find('#band-search-filter-results-blank').hide()
      @screen.find('#band-search-filter-results-filtered').show()
      @screen.find('#band-search-filter-description').html(@searchResults.description)
    
  renderResultsPage: () =>
    super()
    this.renderResultsHeader() if @pageNumber == 1
    bands = @searchResults.bands
    len = bands.length
    if 0 == len
      @screen.find('#band-search-filter-results-list').hide()
      @screen.find('#band-search-filter-results-list-blank').show()
      @screen.find('#band-search-filter-results-list-blank').html('No results found')
      return
    else  
      @screen.find('#band-search-filter-results-list-blank').hide()
      @screen.find('#band-search-filter-results-list').show()
      this.renderBands(bands)

  renderBands: (bands) =>
    toolTip = undefined
    ii = undefined
    len = undefined
    mTemplate = $('#template-find-band-row').html()
    pTemplate = $('#template-band-player-info').html()
    aTemplate = $('#template-band-action-btns').html()
    eTemplate = $('#template-band-edit-btns').html()
    bVals = undefined
    bb = undefined
    renderings = ''
    instr_logos = undefined
    instr = undefined
    players = undefined
    playerVals = undefined
    aPlayer = undefined
    isMember = undefined
    ii = 0
    len = bands.length
    while ii < len
      bb = bands[ii]
      instr_logos = ''
      players = ''
      playerVals = {}
      isMember = false
      jj = 0
      ilen = bb['players'].length
      while jj < ilen
        toolTip = ''
        aPlayer = bb['players'][jj]
        player_instrs = ''
        iter_pinstruments = aPlayer['instruments'].split(',')
        kk = 0
        klen = iter_pinstruments.length
        while kk < klen
          pinstr = iter_pinstruments[kk]
          toolTip = ''
          if pinstr of @instrument_logo_map
            instr = @instrument_logo_map[pinstr].asset
            toolTip = pinstr
          player_instrs += '<img src="' + instr + '" title="' + toolTip + '"/>'
          kk++
        if !isMember
          isMember = aPlayer.user_id == context.JK.currentUserId
        playerVals =
          user_id: aPlayer.user_id
          player_name: aPlayer.name
          profile_url: '/client#/profile/' + aPlayer.user_id
          avatar_url: context.JK.resolveAvatarUrl(aPlayer.photo_url)
          player_instruments: player_instrs
        players += context.JK.fillTemplate(pTemplate, playerVals)
        jj++
      actionVals = undefined
      band_actions = undefined
      if isMember
        actionVals =
          profile_url: '/client#/bandProfile/' + bb.id
          band_edit_url: '/client#/band/setup/' + bb.id + '/step1'
          band_member_url: '/client#/band/setup/' + bb.id + '/step2'
        band_actions = context.JK.fillTemplate(eTemplate, actionVals)
      else
        actionVals =
          profile_url: '/client#/bandProfile/' + bb.id
          button_follow: if bb['is_following'] then '' else 'button-orange'
          button_message: 'button-orange'
        band_actions = context.JK.fillTemplate(aTemplate, actionVals)
      bgenres = ''
      jj = 0
      ilen = bb['genres'].length
      while jj < ilen
        bgenres += bb['genres'][jj]['description'] + '<br />'
        jj++
      bgenres += '<br />'
      bVals =
        avatar_url: context.JK.resolveBandAvatarUrl(bb.photo_url)
        profile_url: '/client#/bandProfile/' + bb.id
        band_name: bb.name
        band_location: bb.city + ', ' + bb.state
        genres: bgenres
        instruments: instr_logos
        biography: bb['biography']
        follow_count: bb['follow_count']
        recording_count: bb['recording_count']
        session_count: bb['session_count']
        band_id: bb['id']
        band_player_template: players
        band_action_template: band_actions
      $rendering = $(context.JK.fillTemplate(mTemplate, bVals))
      $offsetParent = @resultsList.closest('.content')
      data = entity_type: 'band'
      options = 
        positions: [
          'top'
          'bottom'
          'right'
          'left'
        ]
        offsetParent: $offsetParent
      context.JK.helpBubble $('.follower-count', $rendering), 'follower-count', data, options
      context.JK.helpBubble $('.recording-count', $rendering), 'recording-count', data, options
      context.JK.helpBubble $('.session-count', $rendering), 'session-count', data, options
      @resultsList.append $rendering
      ii++

    this._bindFollowBand()

    context.JK.bindHoverEvents()
    return
  
  _bindFollowBand: () =>
    objThis = this
    @screen.find('.search-m-follow').on 'click', (evt) ->
      if 0 == $(this).closest('.button-orange').size()
        return false
      $(this).click (ee) ->
        ee.preventDefault()
        return
      evt.stopPropagation()
      newFollowing = {}
      newFollowing.band_id = $(this).parent().data('band-id')
      url = '/api/users/' + context.JK.currentUserId + '/followings'
      $.ajax
        type: 'POST'
        dataType: 'json'
        contentType: 'application/json'
        url: url
        data: JSON.stringify(newFollowing)
        processData: false
        success: (response) ->
          $('div[data-band-id=' + newFollowing.band_id + '] .search-m-follow').removeClass('button-orange').addClass 'button-grey'
          return
        error: objThis.app.ajaxError(arguments)
    
  _formatLocation: (band) ->

  friendRequestCallback: (user_id)=> 
    # TODO:

  paginate: () =>
    super()

  registerResultsPagination: () =>
    super()

  filterData: () =>
    super()[@searchSubType]

