(function (context, $) {
  "use strict";

  context.JK = context.JK || {};
  context.JK.FindMusicianScreen = function (app) {

    var logger = context.JK.logger;
    var rest = context.JK.Rest();
    var EVENTS = context.JK.EVENTS;
    var musicians = {};
    var musicianList;
    var instrument_logo_map = context.JK.getInstrumentIconMap24();
    var did_show_musician_page = false;
    var page_num = 1, page_count = 0;
    var textMessageDialog = null;
    var $screen = null;
    var $results = null;
    var $spinner = null;
    var $endMusicianList = null;
    var $templateAccountSessionLatency = null;
    var helpBubble = context.JK.HelpBubbleHelper;
    var sessionUtils = context.JK.SessionUtils;
    var $musicianSearchCity = null;
    var $musicianFilterCity = null;
    var $musicianChangeFilterCity = null;
    var $musicianQueryScore = null;
    var $musicianDistance = null;
    var $musicianLatencyOrDistanceLabel = null;
    var $refreshBtn = null;
    var searchLocationOverride = null;
    var currentRequest = null;

    function search() {
      var options = {
        srch_m: 1,
        page: page_num
      }

      // order by
      var orderby = $('#musician_order_by').val();
      if (typeof orderby != 'undefined' && orderby.length > 0) {
        options['orderby'] = orderby;
      }

      // instrument filter
      var instrument = $('#musician_instrument').val();
      if (typeof instrument != 'undefined' && !(instrument === '')) {
        options['instrument'] = instrument;
      }

      // score filter
      var query_param = $musicianQueryScore.val();
      if (query_param !== null) {
        options['score_limit'] = query_param;
      }

      var distance = $musicianDistance.val();
      if (distance !== null) {
        options['distance'] = distance;
      }

      if(searchLocationOverride) {
        options['country'] = searchLocationOverride.countrycode;
        options['region'] = searchLocationOverride.regioncode;
        options['city'] = searchLocationOverride.city;
      }

      $spinner.show();
      $refreshBtn.addClass('disabled')
      currentRequest = rest.searchMusicians(options)
        .done(afterLoadMusicians)
        .fail(function(jqXHR) {
          if(jqXHR.status === 0 && jqXHR.statusText === 'abort') {
            // do nothing
          }
          else {
            app.ajaxError(arguments);
          }
        })
        .always(function() {currentRequest = null; $spinner.hide(); $refreshBtn.removeClass('disabled')})
    }

    function abortCurrentRequest() {
      if(currentRequest) {
        currentRequest.abort()
        currentRequest = null;
        $spinner.hide();
        $refreshBtn.removeClass('disabled')
      }
    }

    function refreshDisplay() {
      abortCurrentRequest();
      clearResults();
      setupSearch();
      search();
    }

    // user clicked refresh
    function manualRefresh() {
      if(!$refreshBtn.is('.disabled')) {
        refreshDisplay();
      }
      return false;
    }

    function changeSearchLocation() {
      app.layout.showDialog('change-search-location').one(EVENTS.DIALOG_CLOSED, function(e, data) {
        if(data.canceled) {
          // do nothing
        }
        else {
          searchLocationOverride = data.result;
          displayUserCity();
          refreshDisplay();
        }
      })

      return false;
    }

    function displayUserCity() {
      app.user().done(function(user) {
        var location = searchLocationOverride || user.geoiplocation;
        var unknown = 'unknown location';
        var result = unknown;
        if(location) {
          var region = location['region'] ? location['region'] : location['regioncode']
          if(!region) { region = 'n/a'; }
          var city = location['city'];
          result = city + ', ' + region;
        }
        $musicianFilterCity.text(result);
      })
    }

    function afterLoadMusicians(mList) {
      did_show_musician_page = true;

      // display the 'no musicians' banner if appropriate
      var $noMusiciansFound = $('#musicians-none-found');
      musicianList = mList;

      if (musicianList.musicians.length == 0) {
        $noMusiciansFound.show();
        musicians = [];
      }
      else {
        $noMusiciansFound.hide();
        musicians = musicianList.musicians;
        if (!(typeof musicians === 'undefined')) {
          if (-1 == page_count) {
            page_count = musicianList['page_count'];
          }
          renderMusicians();
        }
      }
    }

    function score_to_text(score) {
      // these are raw scores as reported by client (round trip times)
      if (score == null) return "n/a";
      return Math.round(score / 2) + " ms";
    }


    function formatLocation(musician) {
      if (musician.city && musician.state) {
        return musician.city + ', ' + musician.regionname
      }
      else if (musician.city) {
        return musician.city
      }
      else if (musician.state) {
        return musician.regionname
      }
      else {
        return 'Location Unavailable'
      }
    }

    function renderMusicians() {
      var ii, len;
      var mTemplate = $('#template-find-musician-row').html();
      var aTemplate = $('#template-musician-action-btns').html();
      var mVals, musician, renderings = '';
      var instr_logos, instr;
      var follows, followVals, aFollow;
      var myAudioLatency = musicianList.my_audio_latency;

      for (ii = 0, len = musicians.length; ii < len; ii++) {
        musician = musicians[ii];
        if (context.JK.currentUserId === musician.id) {
          // VRFS-294.3 (David) => skip if current user is musician
          continue;
        }
        instr_logos = '';
        for (var jj = 0, ilen = musician['instruments'].length; jj < ilen; jj++) {
          var toolTip = '';
          if (musician['instruments'][jj].instrument_id in instrument_logo_map) {
            instr = instrument_logo_map[musician['instruments'][jj].instrument_id].asset;
            toolTip = musician['instruments'][jj].instrument_id;
          }
          instr_logos += '<img src="' + instr + '" title="' + toolTip + '"/>';
        }
        var actionVals = {
          profile_url: "/client#/profile/" + musician.id,
          friend_class: 'button-' + (musician['is_friend'] ? 'grey' : 'orange'),
          friend_caption: (musician.is_friend ? 'DIS' : '') + 'CONNECT',
          follow_class: 'button-' + (musician['is_following'] ? 'grey' : 'orange'),
          follow_caption: (musician.is_following ? 'UN' : '') + 'FOLLOW',
          message_class: 'button-orange',
          message_caption: 'MESSAGE',
          button_message: 'button-orange'
        };
        var musician_actions = context.JK.fillTemplate(aTemplate, actionVals);

        var latencyBadge = context._.template(
          $templateAccountSessionLatency.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: 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']
        };
        var $rendering = $(context.JK.fillTemplate(mTemplate, mVals))

        var $offsetParent = $results.closest('.content');
        var data = {entity_type: 'musician'};
        var options = {positions: ['top', 'bottom', 'right', 'left'], offsetParent: $offsetParent};

        var 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);

        $results.append($rendering);
        $rendering.find('.biography').dotdotdot();
      }


      $('.search-m-friend').on('click', friendMusician);
      $('.search-m-follow').on('click', followMusician);
      $('.search-m-message').on('click', messageMusician);

      context.JK.bindHoverEvents();
    }

    function beforeShow(data) {
    }

    function afterShow(data) {
      if(!did_show_musician_page) {
        // cache page because query is slow, and user may have paginated a bunch
        refreshDisplay();
      }
    }

    function clearResults() {
      musicians = {};
      $('#musician-filter-results .musician-list-result').remove();
      $endMusicianList.hide();
      page_num = 1;
      page_count = -1;
    }

    function setupSearch() {
      var orderby = $('#musician_order_by').val();
      if(orderby == 'distance') {
        $musicianSearchCity.show();
        $musicianDistance.closest('.easydropdown-wrapper').show();
        $musicianQueryScore.closest('.easydropdown-wrapper').hide();
        $musicianLatencyOrDistanceLabel.text('Distance:')
      }
      else {
        $musicianSearchCity.hide();
        $musicianDistance.closest('.easydropdown-wrapper').hide();
        $musicianQueryScore.closest('.easydropdown-wrapper').show();
        $musicianLatencyOrDistanceLabel.text('Latency:')
      }
    }

    function friendMusician(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(function (ee) {
        ee.preventDefault();
      });

      evt.stopPropagation();
      var uid = $(this).parent().data('musician-id');
      rest.sendFriendRequest(app, uid, friendRequestCallback);
    }

    function friendRequestCallback(user_id) {
      // remove the orange look to indicate it's not selectable
// @FIXME -- this will need to be tweaked when we allow unfollowing
      $('div[data-musician-id=' + user_id + '] .search-m-friend').removeClass('button-orange').addClass('button-grey');
    }

    function followMusician(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(function (ee) {
        ee.preventDefault();
      });

      evt.stopPropagation();
      var newFollowing = {};
      newFollowing.user_id = $(this).parent().data('musician-id');
      var url = "/api/users/" + context.JK.currentUserId + "/followings";
      $.ajax({
        type: "POST",
        dataType: "json",
        contentType: 'application/json',
        url: url,
        data: JSON.stringify(newFollowing),
        processData: false,
        success: function (response) {
          // remove the orange look to indicate it's not selectable
          // @FIXME -- this will need to be tweaked when we allow unfollowing
          $('div[data-musician-id=' + newFollowing.user_id + '] .search-m-follow').removeClass('button-orange').addClass('button-grey');
        },
        error: app.ajaxError
      });
    }

    function messageMusician() {
      var userId = $(this).parent().data('musician-id');
      app.layout.showDialog('text-message', { d1: userId });
      return false;
    }


    function events() {
      $musicianQueryScore.change(refreshDisplay);
      $('#musician_instrument').change(refreshDisplay);
      $('#musician_order_by').change(refreshDisplay);
      $musicianDistance.change(refreshDisplay);
      $musicianChangeFilterCity.click(changeSearchLocation);
      $refreshBtn.click(manualRefresh)

      $('#musician-filter-results').closest('.content-body-scroller').bind('scroll', function () {

        // do not check scroll when filling out initial results, which we can tell if page_count == -1
        if(page_count == -1) {return};

        if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
          if (page_num < page_count) {
            page_num += 1;
            search();
          }
          else {
            $endMusicianList.show()
          }
        }
      });
    }

    function initialize(textMessageDialogInstance) {

      textMessageDialog = textMessageDialogInstance;

      var screenBindings = {
        'beforeShow': beforeShow,
        'afterShow': afterShow
      };
      app.bindScreen('musicians', screenBindings);

      $screen = $('#musicians-screen')
      $results = $screen.find('#musician-filter-results');
      $spinner = $screen.find('.paginate-wait')
      $endMusicianList = $screen.find('#end-of-musician-list')
      $templateAccountSessionLatency = $("#template-account-session-latency")
      $musicianSearchCity = $('#musician-search-city');
      $musicianFilterCity = $('#musician-filter-city');
      $musicianChangeFilterCity = $('#musician-change-filter-city');
      $musicianQueryScore = $('#musician_query_score');
      $musicianDistance = $('#musician_distance');
      $musicianLatencyOrDistanceLabel = $screen.find('.latency-or-distance')
      $refreshBtn = $screen.find('.btn-refresh-entries');
      events();
      setupSearch();
      displayUserCity();
    }

    this.initialize = initialize;
    this.renderMusicians = renderMusicians;
    this.afterShow = afterShow;

    this.clearResults = clearResults;

    return this;
  }
})(window, jQuery);
