(function(context,$) {

  "use strict";

  context.JK = context.JK || {};

  // TODO: Add a target type, which can be band or user -- call the
  // appropriate API methods.
  context.JK.AccountProfileSamples = function(app, parent, loadFn, updateFn) {
    var $document = $(document)

    // used to initialize RecordingSourceValidator in site_validator.js.coffee
    var jamkazamRecordingSources = [];
    var soundCloudRecordingSources = [];
    var youTubeRecordingSources = [];

    var logger = context.JK.logger;
    var EVENTS = context.JK.EVENTS;
    var api = context.JK.Rest();
    var ui = new context.JK.UIHelper(JK.app);
    var target = {};
    var profileUtils = context.JK.ProfileUtils;

    var $screen = $('.profile-online-sample-controls', parent);
    // online presences
    var $website = $screen.find('.website');
    var $soundCloudUsername = $screen.find('.soundcloud-username');
    var $reverbNationUsername = $screen.find('.reverbnation-username');
    var $bandCampUsername = $screen.find('.bandcamp-username');
    var $fandalismUsername = $screen.find('.fandalism-username');
    var $youTubeUsername = $screen.find('.youtube-username');
    var $facebookUsername = $screen.find('.facebook-username');
    var $twitterUsername = $screen.find('.twitter-username');

    // performance samples
    var $jamkazamSampleList = $screen.find(".sample-list[source-type='jamkazam']")
    var $soundCloudSampleList = $screen.find(".sample-list[source-type='soundcloud']")
    var $youTubeSampleList = $screen.find(".sample-list[source-type='youtube']")

    // buttons
    var $btnAddJkRecording = $screen.find('.btn-add-jk-recording')
    var $btnCancel = parent.find('.account-edit-profile-cancel')
    var $btnBack = parent.find('.account-edit-profile-back')
    var $btnSubmit = parent.find('.account-edit-profile-submit')

    var urlValidator=null
    var soundCloudValidator=null
    var reverbNationValidator=null
    var bandCampValidator=null
    var fandalismValidator=null
    var youTubeValidator=null
    var facebookValidator=null
    var twitterValidator=null
    var soundCloudRecordingValidator=null
    var youTubeRecordingValidator=null

    function beforeShow(data) {
    }

    function afterShow(data) {
      if (window.ProfileStore.solo) {
        $btnBack.hide()
        $btnSubmit.text('SAVE & RETURN TO PROFILE');
      }
      else {
        $btnBack.show()
        $btnSubmit.text('SAVE & FINISH');
      }

      $.when(loadFn())
        .done(function(targetPlayer) {
          if (targetPlayer) {
            renderPlayer(targetPlayer)
          }
        })
    }

    function renderPlayer(targetPlayer) {
      renderPresence(targetPlayer);
      renderSamples(targetPlayer);
    }

    function renderPresence(targetPlayer) {
      $website.val(targetPlayer.website);

      // SoundCloud
      var presences = profileUtils.soundCloudPresences(targetPlayer.online_presences);
      if (presences && presences.length > 0) {
        $soundCloudUsername.val(presences[0].username);
      }

      // ReverbNation
      presences = profileUtils.reverbNationPresences(targetPlayer.online_presences);
      if (presences && presences.length > 0) {
        $reverbNationUsername.val(presences[0].username);
      }

      // Bandcamp
      presences = profileUtils.bandCampPresences(targetPlayer.online_presences);
      if (presences && presences.length > 0) {
        $bandCampUsername.val(presences[0].username);
      }

      // Fandalism
      presences = profileUtils.fandalismPresences(targetPlayer.online_presences);
      if (presences && presences.length > 0) {
        $fandalismUsername.val(presences[0].username);
      }

      // YouTube
      presences = profileUtils.youTubePresences(targetPlayer.online_presences);
      if (presences && presences.length > 0) {
        $youTubeUsername.val(presences[0].username);
      }

      // Facebook
      presences = profileUtils.facebookPresences(targetPlayer.online_presences);
      if (presences && presences.length > 0) {
        $facebookUsername.val(presences[0].username);
      }

      // Twitter
      presences = profileUtils.twitterPresences(targetPlayer.online_presences);
      if (presences && presences.length > 0) {
        $twitterUsername.val(presences[0].username);
      }
    }

    function renderSamples(targetPlayer) {
      // JamKazam recordings
      var samples = profileUtils.jamkazamSamples(targetPlayer.performance_samples);
      loadSamples(samples, 'jamkazam', $jamkazamSampleList, jamkazamRecordingSources);

      // SoundCloud recordings
      samples = profileUtils.soundCloudSamples(targetPlayer.performance_samples);
      loadSamples(samples, 'soundcloud', $soundCloudSampleList, soundCloudRecordingSources);

      // YouTube videos
      samples = profileUtils.youTubeSamples(targetPlayer.performance_samples);
      loadSamples(samples, 'youtube', $youTubeSampleList, youTubeRecordingSources);
    }

    function loadSamples(samples, type, $sampleList, recordingSources) {
      $sampleList.find(":not(.empty)").remove();

      if (type === 'jamkazam') {
        $.each(samples, function(index, val) {
          recordingSources.push({
            'claimed_recording_id': val.claimed_recording.id,
            'description': val.claimed_recording.name
          });

          buildJamkazamEntry(val.claimed_recording.id, val.claimed_recording.name);
        });
      } else {
        if (samples && samples.length > 0) {
          $.each(samples, function(index, val) {

            var source = {
              'url': val.url,
              'recording_id': val.service_id,
              'recording_title': val.description
            }
            recordingSources.push(source);
            buildNonJamKazamEntry($sampleList, type, source);
          });
        }
      }
    }

    function buildNonJamKazamEntry($sampleList, type, source) {

      // remove anything that matches
      $sampleList.find('[data-recording-id=' + source.recording_id + ']').remove();

      // TODO: this code is repeated in HTML file
      var recordingIdAttr = ' data-recording-id="' + source.recording_id + '" ';
      var recordingUrlAttr = ' data-recording-url="' + source.url + '" ';
      var recordingTitleAttr = ' data-recording-title="' + source.recording_title + '"';
      var title = formatTitle(source.recording_title);
      $sampleList.find(".empty").addClass("hidden")
      $sampleList.append('<div class="clearall recording-row left entry"' + recordingIdAttr + recordingUrlAttr + recordingTitleAttr + '>' + title + '</div>');
      $sampleList.append('<div class="right close-button" data-recording-type="' + type + '"' + recordingIdAttr + '>X</div>');
    }

    function buildJamkazamEntry(recordingId, recordingName) {
      var title = formatTitle(recordingName);

      var recordingIdAttr = ' data-recording-id="' + recordingId + '" ';
      $jamkazamSampleList.append('<div class="clearall recording-row left entry"' + recordingIdAttr + '>' + title + '</div>');
      $jamkazamSampleList.append('<div class="right close-button" data-recording-type="jamkazam"' + recordingIdAttr + '>X</div>');
    }

    function events() {

      // buttons
      $btnAddJkRecording.click(function(evt) {
        evt.preventDefault();

        ui.launchRecordingSelectorDialog(jamkazamRecordingSources, function(selectedRecordings) {
          $jamkazamSampleList.empty();

          jamkazamRecordingSources = [];

          // update the list with the selected recordings
          $.each(selectedRecordings, function(index, val) {
            jamkazamRecordingSources.push({
              'claimed_recording_id': val.id,
              'description': val.name
            });

            buildJamkazamEntry(val.id, val.name);
          });
        });


        return false;
      });

      $btnCancel.click(function(evt) {
        evt.stopPropagation();

        window.ProfileActions.cancelProfileEdit()

        return false;
      });

      $btnBack.click(function(evt) {
        evt.stopPropagation();
        navigateTo('/client#/account/profile/interests');
        return false;
      });

      enableSubmits();

      $screen.find(".sample-list").off("click").on("click", ".close-button", function(e) {
        removeRow($(this).data("recording-id"), $(this).data("recording-type"))
      })
    }

    function enableSubmits() {
      $btnSubmit.off("click").on("click", function(e) {
        e.stopPropagation();
        handleUpdateProfile();
        return false;
      })

      $btnSubmit.removeClass("disabled")
    }

    function disableSubmits() {
      $btnSubmit.addClass("disabled")
      $btnSubmit.off("click")
    }

    function validate() {
      var errors = $screen.find('.site_validator.error');
      return !(errors && errors.length > 0);
    }

    function navigateTo(targetLocation) {
      context.location = targetLocation;
    }

    function addOnlinePresence(presenceArray, username, type) {
      if ($.trim(username).length > 0) {
        presenceArray.push({
          'player_id': context.JK.currentUserId,
          'service_type': type,
          'username': username
        });
      }
    }

    function addPerformanceSamples(sampleArray, $samplesSelector, type) {
      var rows = $samplesSelector.find('.recording-row');

      // loop over rows, extracting service id, description, and url
      rows.each(function(index) {
        var id = $(this).attr('data-recording-id');

        if (type === 'jamkazam') {
          sampleArray.push({
            'player_id': context.JK.currentUserId,
            'service_type': type,
            'claimed_recording_id': id,
          });
        } else {
          var url = $(this).attr('data-recording-url');
          var title = $(this).attr('data-recording-title');

          sampleArray.push({
            'player_id': context.JK.currentUserId,
            'service_type': type,
            'service_id': id,
            'url': url,
            'description': title
          });
        }
      });
    }

    function handleUpdateProfile() {
      disableSubmits()

      var player = buildPlayer()

      updateFn({
        website: player.website,
        online_presences: player.online_presences,
        performance_samples: player.performance_samples
      })
      .done(postUpdateProfileSuccess)
      .fail(postUpdateProfileFailure)
      .always(enableSubmits);
    }

    function buildPlayer() {
      // extract online presences
      var op = [];
      var presenceTypes = profileUtils.ONLINE_PRESENCE_TYPES;
      addOnlinePresence(op, $soundCloudUsername.val(), presenceTypes.SOUNDCLOUD.description);
      addOnlinePresence(op, $reverbNationUsername.val(), presenceTypes.REVERBNATION.description);
      addOnlinePresence(op, $bandCampUsername.val(), presenceTypes.BANDCAMP.description);
      addOnlinePresence(op, $fandalismUsername.val(), presenceTypes.FANDALISM.description);
      addOnlinePresence(op, $youTubeUsername.val(), presenceTypes.YOUTUBE.description);
      addOnlinePresence(op, $facebookUsername.val(), presenceTypes.FACEBOOK.description);
      addOnlinePresence(op, $twitterUsername.val(), presenceTypes.TWITTER.description);

      // extract performance samples
      var ps = [];
      var performanceSampleTypes = profileUtils.SAMPLE_TYPES;
      addPerformanceSamples(ps, $jamkazamSampleList, performanceSampleTypes.JAMKAZAM.description);
      addPerformanceSamples(ps, $soundCloudSampleList, performanceSampleTypes.SOUNDCLOUD.description);
      addPerformanceSamples(ps, $youTubeSampleList, performanceSampleTypes.YOUTUBE.description);

      var website = $website.val()
      if (website == '') {
        website = null;
      }

      return {
        website: website,
        online_presences: op,
        performance_samples: ps
      }
    }

    function postUpdateProfileSuccess(response) {
      $document.triggerHandler(EVENTS.USER_UPDATED, response);
      ProfileActions.doneProfileEdit()
    }

    function postUpdateProfileFailure(xhr, textStatus, errorMessage) {

      var errors = JSON.parse(xhr.responseText)

      if(xhr.status == 422) {

      } else {
        app.ajaxError(xhr, textStatus, errorMessage)
      }
    }

    function removeRow(recordingId, type) {
      $('div[data-recording-id=' + recordingId + ']').remove();
      var sampleList = $('.sample-list[source-type="' + type + '"]')
      var rowCnt = sampleList.find('.recording-row').length
      if (0==parseInt(rowCnt)) {
        sampleList.find(".empty").removeClass("hidden")
      }

      if (type === 'soundcloud') {
        soundCloudRecordingValidator.removeRecordingId(recordingId);
      } else if (type === 'youtube') {
        youTubeRecordingValidator.removeRecordingId(recordingId);
      }
    }

    function formatTitle(title) {
      return title;
    }

    // This function is a bit of a mess.  It was pulled
    // from the html.erb file verbatim, and could use a
    // refactor:
    function initializeValidators() {
      var initialized = false;
      //$document.on('JAMKAZAM_READY', function(e, data) {
        JK.JamServer.get$Server().on(JK.EVENTS.CONNECTION_UP, function() {
          if(initialized) {
            return;
          }
          initialized = true;

          //var $screen = $('#account-profile-samples');
          var $btnAddSoundCloudRecording = $screen.find('.btn-add-soundcloud-recording');
          var $btnAddYouTubeVideo = $screen.find('.btn-add-youtube-video');
          // var $soundCloudSampleList = $screen.find('.samples.soundcloud');
          // var $youTubeSampleList = $screen.find('.samples.youtube');


          setTimeout(function() {
            urlValidator = new JK.SiteValidator('url', websiteSuccessCallback, userNameFailCallback, parent)
            urlValidator.init()

            soundCloudValidator = new JK.SiteValidator('soundcloud', userNameSuccessCallback, userNameFailCallback, parent)
            soundCloudValidator.init()

            reverbNationValidator = new JK.SiteValidator('reverbnation', userNameSuccessCallback, userNameFailCallback, parent)
            reverbNationValidator.init()

            bandCampValidator = new JK.SiteValidator('bandcamp', userNameSuccessCallback, userNameFailCallback, parent)
            bandCampValidator.init()

            fandalismValidator = new JK.SiteValidator('fandalism', userNameSuccessCallback, userNameFailCallback, parent)
            fandalismValidator.init()

            youTubeValidator = new JK.SiteValidator('youtube', userNameSuccessCallback, userNameFailCallback, parent)
            youTubeValidator.init()

            facebookValidator = new JK.SiteValidator('facebook', userNameSuccessCallback, userNameFailCallback, parent)
            facebookValidator.init()

            twitterValidator = new JK.SiteValidator('twitter', userNameSuccessCallback, userNameFailCallback, parent)
            twitterValidator.init()

            soundCloudRecordingValidator = new JK.RecordingSourceValidator('rec_soundcloud', soundCloudSuccessCallback, siteFailCallback, parent)
            youTubeRecordingValidator = new JK.RecordingSourceValidator('rec_youtube', youTubeSuccessCallback, siteFailCallback, parent)

            soundCloudRecordingValidator.init(soundCloudRecordingSources)
            youTubeRecordingValidator.init(youTubeRecordingSources)
          }, 1)

          function userNameSuccessCallback($inputDiv) {
            $inputDiv.removeClass('error');
            $inputDiv.find('.error-text').remove();
          }

          function userNameFailCallback($inputDiv) {
            $inputDiv.addClass('error');
            $inputDiv.find('.error-text').remove();
            $inputDiv.append("<span class='error-text'>Invalid username</span>").show();
          }

          function websiteSuccessCallback($inputDiv) {
            $inputDiv.removeClass('error');
            $inputDiv.find('.error-text').remove();
          }


          function soundCloudSuccessCallback($inputDiv) {
            siteSuccessCallback($inputDiv, soundCloudRecordingValidator, $soundCloudSampleList, 'soundcloud');
          }

          function youTubeSuccessCallback($inputDiv) {
            siteSuccessCallback($inputDiv, youTubeRecordingValidator, $youTubeSampleList, 'youtube');
          }

          function siteSuccessCallback($inputDiv, recordingSiteValidator, $sampleList, type) {
            $sampleList.find(".empty").addClass("hidden")
            $inputDiv.removeClass('error');
            $inputDiv.find('.error-text').remove();

            var recordingSources = recordingSiteValidator.recordingSources();
            if (recordingSources && recordingSources.length > 0) {
              var addedRecording = recordingSources[recordingSources.length-1];

              buildNonJamKazamEntry($sampleList, type, addedRecording);
            }

            $inputDiv.find('input').val('');
          }

          function siteFailCallback($inputDiv) {
            $inputDiv.addClass('error');
            $inputDiv.find('.error-text').remove();
            $inputDiv.append("<span class='error-text'>Invalid URL</span>").show();
          }
        });
      //});



    } // end initializeValidators.

    function resetForm() {
      $("input", $screen).val("")
    }

    function initialize() {
      var screenBindings = {
        'beforeShow': beforeShow,
        'afterShow': afterShow
      };

      // We only want to bind this screen for accounts:
      if (updateFn.name===api.updateUser.name) {
        // A little hacky, but we are soon going to replace this:
        app.bindScreen('account/profile/samples', screenBindings);
      }

      initializeValidators();
      events();
    }

    this.initialize = initialize;
    this.beforeShow = beforeShow;
    this.afterShow = afterShow;
    this.buildPlayer = buildPlayer;
    this.renderPlayer = renderPlayer
    this.resetForm = resetForm;
    return this;
  };
})(window,jQuery);