(function (context, $) {

  "use strict";

  context.JK = context.JK || {};
  context.JK.AccountProfileScreen = function (app) {
    var $document = $(document);
    var logger = context.JK.logger;
    var EVENTS = context.JK.EVENTS;
    var NAMED_MESSAGES = context.JK.NAMED_MESSAGES;
    var api = context.JK.Rest();
    var userId;
    var user = {};
    var selectLocation = null;
    var recentUserDetail = null;
    var loadingCitiesData = false;
    var loadingRegionsData = false;
    var loadingCountriesData = false;
    var nilOptionStr = '<option value=""></option>';
    var nilOptionText = 'n/a';
    var $screen = $('#account-profile-basics');
    var $avatar = $screen.find('#avatar');
    var $country = $screen.find('#country');
    var $region = $screen.find('#region');
    var $city = $screen.find('#city');
    var $firstName = $screen.find('#first-name');
    var $lastName = $screen.find('#last-name');
    var $gender = $screen.find('#gender');
    var $biography = $screen.find('#biography');
    var $subscribe = $screen.find('#subscribe');

    var $btnCancel = $screen.find('.account-edit-profile-cancel');
    var $btnSubmit = $screen.find('.account-edit-profile-submit');

    function beforeShow(data) {
      userId = data.id;
    }

    function afterShow(data) {
      if (window.ProfileStore.solo) {
        $btnSubmit.text('SAVE & RETURN TO PROFILE');
      }
      else {
        $btnSubmit.text('SAVE & NEXT');
      }
      resetForm();
      renderAccountProfile();
    }

    function resetForm() {
      // remove all display errors
      $('#account-profile-content-scroller form .error-text').remove()
      $('#account-profile-content-scroller form .error').removeClass("error")
    }

    function populateAccountProfile(userDetail) {

      $avatar.attr('src', context.JK.resolveAvatarUrl(userDetail.photo_url));
      $country.val(userDetail.country);
      $region.val(userDetail.state);
      $city.val(userDetail.city);
      $firstName.val(userDetail.first_name);
      $lastName.val(userDetail.last_name);
      $gender.val(userDetail.gender);
      $biography.val(userDetail.biography);

      if (userDetail.subscribe_email) {
        $subscribe.attr('checked', 'checked');
      }

      var content_root = $('#account-profile-content-scroller');

      // set birth_date
      if (userDetail.birth_date) {
        var birthDateFields = userDetail.birth_date.split('-')
        var birthDateYear = birthDateFields[0];
        var birthDateMonth = birthDateFields[1];
        var birthDateDay = birthDateFields[2];

        $('select#user_birth_date_1i', content_root).val(parseInt(birthDateYear));
        $('select#user_birth_date_2i', content_root).val(parseInt(birthDateMonth));
        $('select#user_birth_date_3i', content_root).val(parseInt(birthDateDay));
      }
    }

    function populateAccountProfileLocation(userDetail, regions, cities) {
      populateRegions(regions, userDetail.state);
      populateCities(cities, userDetail.city);
    }

    function populateCountries(countries, userCountry) {

      // countries has the format ["US", ...]
      var foundCountry = false;
      var countrySelect = getCountryElement();
      countrySelect.children().remove();

      var nilOption = $(nilOptionStr);
      nilOption.text(nilOptionText);
      countrySelect.append(nilOption);

      $.each(countries, function (index, country) {
        if (!country) return;

        var option = $(nilOptionStr);
        option.text(country);
        option.attr("value", country);

        if (country == userCountry) {
          foundCountry = true;
        }

        countrySelect.append(option);
      });

      if (!foundCountry) {
        // in this case, the user has a country that is not in the database
        // this can happen in a development/test scenario, but let's assume it can
        // happen in production too.
        var option = $(nilOptionStr);
        option.text(userCountry);
        option.attr("value", userCountry);
        countrySelect.append(option);
      }

      countrySelect.val(userCountry);
      countrySelect.attr("disabled", null)
    }


    function populateCountriesx(countriesx, userCountry) {

      // countriesx has the format [{countrycode: "US", countryname: "United States"}, ...]

      var foundCountry = false;
      var countrySelect = getCountryElement();
      countrySelect.children().remove();

      var nilOption = $(nilOptionStr);
      nilOption.text(nilOptionText);
      countrySelect.append(nilOption);

      $.each(countriesx, function (index, countryx) {
        if (!countryx.countrycode) return;

        var option = $(nilOptionStr);
        option.text(countryx.countryname);
        option.attr("value", countryx.countrycode);

        if (countryx.countrycode == userCountry) {
          foundCountry = true;
        }

        countrySelect.append(option);
      });

      if (!foundCountry) {
        // in this case, the user has a country that is not in the database
        // this can happen in a development/test scenario, but let's assume it can
        // happen in production too.
        var option = $(nilOptionStr);
        option.text(userCountry);
        option.attr("value", userCountry);
        countrySelect.append(option);
      }

      countrySelect.val(userCountry);
      countrySelect.attr("disabled", null);
    }

    function populateRegions(regions, userRegion) {
      var regionSelect = getRegionElement()
      regionSelect.children().remove()

      var nilOption = $(nilOptionStr);
      nilOption.text(nilOptionText);
      regionSelect.append(nilOption);

      $.each(regions, function (index, region) {
        if (!region) return;

        var option = $(nilOptionStr);
        option.text(region['name']);
        option.attr("value", region['region']);

        regionSelect.append(option);
      })

      regionSelect.val(userRegion)
      regionSelect.attr("disabled", null)
    }

    function populateCities(cities, userCity) {
      var citySelect = getCityElement();
      citySelect.children().remove();

      var nilOption = $(nilOptionStr);
      nilOption.text(nilOptionText);
      citySelect.append(nilOption);

      $.each(cities, function (index, city) {
        if (!city) return;

        var option = $(nilOptionStr);
        option.text(city);
        option.attr("value", city);

        citySelect.append(option);
      });

      citySelect.val(userCity);
      citySelect.attr("disabled", null);
    }

    /****************** MAIN PORTION OF SCREEN *****************/
    // events for main screen
    function events() {
      $btnCancel.click(function (evt) {
        evt.stopPropagation();
        window.ProfileActions.cancelProfileEdit()
        return false;
      });

      $('#account-profile-content-scroller').on('click', '#account-change-avatar', function (evt) {
        evt.stopPropagation();
        navToAvatar();
        return false;
      });

      enableSubmits();
    }

    function teacherGuidance() {

      if(recentUserDetail && recentUserDetail.is_a_teacher) {
          setTimeout(function() {
            var $header  = $('#account-edit-profile-form h2')
            context.JK.HelpBubbleHelper.teacherMusicianProfile($header, $screen);
          }, 2000)
      }

    }
    function renderAccountProfile() {

      $.when(api.getUserProfile())
        .done(function (userDetail) {
          recentUserDetail = userDetail;
          populateAccountProfile(userDetail);
          teacherGuidance();
          selectLocation = new context.JK.SelectLocation(getCountryElement(), getRegionElement(), getCityElement(), app);
          selectLocation.load(userDetail.country, userDetail.state, userDetail.city)
        });
    }

    function navToAccount() {
      resetForm();
      window.location = '/client#/profile/' + context.JK.currentUserId;
    }

    function navToAvatar() {
      resetForm();
      window.location = '/client#/account/profile/avatar';
    }

    function handleUpdateProfile() {
      disableSubmits();
      resetForm();

      var country = getCountryElement().val();
      var region = getRegionElement().val();
      var city = getCityElement().val();
      var firstName = getFirstNameElement().val();
      var lastName = getLastNameElement().val();
      var gender = getGenderElement().val();
      var subscribeEmail = getSubscribeEmail().is(':checked');
      var birthDate = getBirthDate();
      var biography = $biography.val();

      api.updateUser({
        country: country,
        state: region,
        city: city,
        first_name: firstName,
        last_name: lastName,
        gender: gender,
        birth_date: birthDate,
        biography: biography,
        subscribe_email: subscribeEmail
      })
        .done(postUpdateProfileSuccess)
        .fail(postUpdateProfileFailure)
        .always(enableSubmits)
    }

    function enableSubmits() {
      $btnSubmit.click(function (evt) {
        evt.stopPropagation();
        handleUpdateProfile();
        return false;
      });
      $btnSubmit.removeClass("disabled");
      $('#account-profile-content-scroller').on('submit', '#account-edit-email-form', function (evt) {
        evt.stopPropagation();
        handleUpdateProfile();
        return false;
      });
      $("#account-edit-email-form").removeClass("disabled");
    }

    function disableSubmits() {
      $("#account-edit-email-form").addClass("disabled")
      $("#account-edit-email-form").off("click")
      $btnSubmit.addClass("disabled")
      $btnSubmit.off("click")
    }

    function postUpdateProfileSuccess(response) {
      $document.triggerHandler(EVENTS.USER_UPDATED, response);
      window.ProfileActions.editProfileNext('experience');
    }

    function postUpdateProfileFailure(xhr, textStatus, errorMessage) {

      var errors = JSON.parse(xhr.responseText)

      if (xhr.status == 422) {
        var first_name = context.JK.format_errors("first_name", errors);
        var last_name = context.JK.format_errors("last_name", errors);
        var country = context.JK.format_errors("country", errors);
        var state = context.JK.format_errors("state", errors);
        var city = context.JK.format_errors("city", errors);
        var birth_date = context.JK.format_errors("birth_date", errors);
        var gender = context.JK.format_errors("birth_date", errors);
        var subscribeEmail = context.JK.format_errors("subscribe_email", errors);
        var biography = context.JK.format_errors("biography", errors);

        if (first_name != null) {
          getFirstNameElement().closest('div.field').addClass('error').end().after(first_name);
        }

        if (last_name != null) {
          getLastNameElement().closest('div.field').addClass('error').end().after(last_name);
        }

        if (country != null) {
          getCountryElement().closest('div.field').addClass('error').end().after(country);
        }

        if (state != null) {
          getRegionElement().closest('div.field').addClass('error').end().after(state);
        }

        if (city != null) {
          getCityElement().closest('div.field').addClass('error').end().after(city);
        }

        if (birth_date != null) {
          getYearElement().closest('div.field').addClass('error').end().after(birth_date);
        }

        if (subscribeEmail != null) {
          getSubscribeEmail().closest('div.field').addClass('error').end().after(subscribeEmail);
        }

        if (gender != null) {
          getGenderElement().closest('div.field').addClass('error').end().after(gender);
        }

        if (biography != null) {
          getBiographyElement().closest('div.field').addClass('error').end().after(biography);
        }
      }
      else {
        app.ajaxError(xhr, textStatus, errorMessage)
      }
    }

    function handleCountryChanged() {
      var selectedCountry = getCountryElement().val()
      var selectedRegion = getRegionElement().val()
      var cityElement = getCityElement();

      updateRegionList(selectedCountry, getRegionElement());
      updateCityList(selectedCountry, null, cityElement);
    }

    function updateRegionList(selectedCountry, regionElement) {
      // only update region
      if (selectedCountry) {
        // set city disabled while updating
        regionElement.attr('disabled', true);
        loadingRegionsData = true;

        regionElement.children().remove()
        regionElement.append($(nilOptionStr).text('loading...'))

        api.getRegions({country: selectedCountry})
          .done(getRegionsDone)
          .error(function (err) {
            regionElement.children().remove()
            regionElement.append($(nilOptionStr).text(nilOptionText))
          })
          .always(function () {
            loadingRegionsData = false;
          });
      }
      else {
        regionElement.children().remove()
        regionElement.append($(nilOptionStr).text(nilOptionText))
      }
    }

    function updateCityList(selectedCountry, selectedRegion, cityElement) {
      logger.debug("updating city list: selectedCountry %o, selectedRegion %o", selectedCountry, selectedRegion);

      // only update cities
      if (selectedCountry && selectedRegion) {
        // set city disabled while updating
        cityElement.attr('disabled', true);
        loadingCitiesData = true;

        cityElement.children().remove();
        cityElement.append($(nilOptionStr).text('loading...'));

        api.getCities({country: selectedCountry, region: selectedRegion})
          .done(getCitiesDone)
          .error(function (err) {
            cityElement.children().remove();
            cityElement.append($(nilOptionStr).text(nilOptionText));
          })
          .always(function () {
            loadingCitiesData = false;
          });
      }
      else {
        cityElement.children().remove();
        cityElement.append($(nilOptionStr).text(nilOptionText));
      }
    }

    function handleRegionChanged() {
      var selectedCountry = getCountryElement().val()
      var selectedRegion = getRegionElement().val()
      var cityElement = getCityElement();

      updateCityList(selectedCountry, selectedRegion, cityElement);
    }

    function getCitiesDone(data) {
      populateCities(data['cities'], recentUserDetail.city);
    }

    function getRegionsDone(data) {
      populateRegions(data['regions'], recentUserDetail.state);
      updateCityList(getCountryElement().val(), getRegionElement().val(), getCityElement());
    }

    function getCountryElement() {
      return $('#account-profile-content-scroller select[name=country]');
    }

    function getRegionElement() {
      return $('#account-profile-content-scroller select[name=region]');
    }

    function getCityElement() {
      return $('#account-profile-content-scroller select[name=city]');
    }

    function getFirstNameElement() {
      return $('#account-profile-content-scroller input[name=first_name]');
    }

    function getLastNameElement() {
      return $('#account-profile-content-scroller input[name=last_name]');
    }

    function getGenderElement() {
      return $('#account-profile-content-scroller select[name=gender]');
    }

    function getMonthElement() {
      return $('#account-profile-content-scroller select#user_birth_date_2i');
    }

    function getDayElement() {
      return $('#account-profile-content-scroller select#user_birth_date_3i');
    }

    function getYearElement() {
      return $('#account-profile-content-scroller select#user_birth_date_1i');
    }

    function getSubscribeEmail() {
      return $('#account-profile-content-scroller input[name=subscribe_email]');
    }

    function getBiographyElement() {
      return $('#account-profile-content-scroller textarea[name=biography]');
    }

    function getBirthDate() {
      var monthElement = getMonthElement()
      if(!monthElement)
      {
        return null;
      }
      var month = getMonthElement().val()
      var day = getDayElement().val()
      var year = getYearElement().val()

      if (month != null && month.length > 0 && day != null && day.length > 0 && year != null && year.length > 0) {
        return month + "-" + day + "-" + year;
      }
      else {
        return null;
      }
    }

    function initialize() {
      var screenBindings = {
        'beforeShow': beforeShow,
        'afterShow': afterShow
      };
      app.bindScreen('account/profile', screenBindings);
      events();
    }

    this.initialize = initialize;
    this.beforeShow = beforeShow;
    this.afterShow = afterShow;
    return this;
  };

})(window, jQuery);