/**
 * @file
 */
(function ($) {

  Drupal.behaviors.dateYearRange = {};

  Drupal.behaviors.dateYearRange.attach = function (context, settings) {
    var $textfield, $textfields, i;

    // Turn the years back and forward fieldsets into dropdowns.
    $textfields = $('input.select-list-with-custom-option', context).once('date-year-range');
    for (i = 0; i < $textfields.length; i++) {
      $textfield = $($textfields[i]);
      new Drupal.dateYearRange.SelectListWithCustomOption($textfield);
    }
  };

  Drupal.dateYearRange = {};

  /**
 * Constructor for the SelectListWithCustomOption object.
 *
 * This object is responsible for turning the years back and forward textfields
 * into dropdowns with an 'other' option that lets the user enter a custom
 * value.
 */
  Drupal.dateYearRange.SelectListWithCustomOption = function ($textfield) {
    this.$textfield = $textfield;
    this.$description = $textfield.next('div.description');
    this.defaultValue = $textfield.val();
    this.$dropdown = this.createDropdown();
    this.$dropdown.insertBefore($textfield);
  };

  /**
   * Get the value of the textfield as it existed on page load.
   *
   * @param {String} type
   *   The type of the variable to be returned. Defaults to string.
   *
   * @return
   *   The original value of the textfield. Returned as an integer, if the type
   *   parameter was 'int'.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.getOriginal = function (type) {
    var original;
    if (type === 'int') {
      original = parseInt(this.defaultValue, 10);
      if (window.isNaN(original)) {
        original = 0;
      }
    }
    else {
      original = this.defaultValue;
    }
    return original;
  };

  /**
   * Get the correct first value for the dropdown.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.getStartValue = function () {
    var direction = this.getDirection();
    var start;
    switch (direction) {
      case 'back':
        // For the 'years back' dropdown, the first option should be -10, unless
        // the default value of the textfield is even smaller than that.
        start = Math.min(this.getOriginal('int'), -10);
      break;

      case 'forward':
        start = 0;
      break;
    }
    return start;
  };

  /**
   * Get the correct last value for the dropdown.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.getEndValue = function () {
    var direction = this.getDirection();
    var end;
    var originalString = this.getOriginal();
    switch (direction) {
      case 'back':
        end = 0;
      break;

      case 'forward':
        // If the original value of the textfield is an absolute year such as
        // 2020, don't try to include it in the dropdown.
        if (originalString.indexOf('+') === -1) {
          end = 10;
        }
        // If the original value is a relative value (+x), we want it to be
        // included in the possible dropdown values.
        else {
          end = Math.max(this.getOriginal('int'), 10);
        }
      break;
    }
    return end;
  };

  /**
   * Create a dropdown select list with the correct options for this textfield.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.createDropdown = function () {
    var $dropdown = $('<select>').addClass('form-select date-year-range-select');
    var $option, i, value;
    var start = this.getStartValue();
    var end = this.getEndValue();
    var direction = this.getDirection();
    for (i = start; i <= end; i++) {
      // Make sure we include the +/- sign in the option value.
      value = i;
      if (i > 0) {
        value = '+' + i;
      }
      // Zero values must have a + or - in front.
      if (i === 0) {
        if (direction === 'back') {
          value = '-' + i;
        }
        else {
          value = '+' + i;
        }
      }
      $option = $('<option>' + Drupal.formatPlural(value, '@count year from now', '@count years from now') + '</option>').val(value);
      $dropdown.append($option);
    }
    // Create an 'Other' option.
    $option = $('<option class="custom-option">' + Drupal.t('Other') + '</option>').val('');
    $dropdown.append($option);

    // When the user changes the selected option in the dropdown, perform
    // appropriate actions (such as showing or hiding the textfield).
    $dropdown.bind('change', $.proxy(this.handleDropdownChange, this));

    // Set the initial value of the dropdown.
    this._setInitialDropdownValue($dropdown);
    return $dropdown;
  };

  Drupal.dateYearRange.SelectListWithCustomOption.prototype._setInitialDropdownValue = function ($dropdown) {
    var textfieldValue = this.getOriginal();
    // Determine whether the original textfield value exists in the dropdown.
    var possible = $dropdown.find('option[value="' + textfieldValue + '"]');
    // If the original textfield value is one of the dropdown options, preselect
    // it and hide the 'other' textfield.
    if (possible.length) {
      $dropdown.val(textfieldValue);
      this.hideTextfield();
    }
    // If the original textfield value isn't one of the dropdown options, choose
    // the 'Other' option in the dropdown.
    else {
      $dropdown.val('');
    }
  };

  /**
   * Determine whether this is the "years back" or "years forward" textfield.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.getDirection = function () {
    if (this.direction) {
      return this.direction;
    }
    var direction;
    if (this.$textfield.hasClass('back')) {
      direction = 'back';
    }
    else if (this.$textfield.hasClass('forward')) {
      direction = 'forward';
    }
    this.direction = direction;
    return direction;
  };

  /**
   * Change handler for the dropdown, to modify the textfield as appropriate.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.handleDropdownChange = function () {
    // Since the dropdown changed, we need to make the content of the textfield
    // match the (new) selected option.
    this.syncTextfield();

    // Show the textfield if the 'Other' option was selected, and hide it if one
    // of the preset options was selected.
    if ($(':selected', this.$dropdown).hasClass('custom-option')) {
      this.revealTextfield();
    }
    else {
      this.hideTextfield();
    }
  };

  /**
   * Display the textfield and its description.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.revealTextfield = function () {
    this.$textfield.show();
    this.$description.show();
  };

  /**
   * Hide the textfield and its description.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.hideTextfield = function () {
    this.$textfield.hide();
    this.$description.hide();
  };

  /**
   * Copy the selected value of the dropdown to the textfield.
   *
   * FAPI doesn't know about the JS-only dropdown, so the textfield needs to
   * reflect the value of the dropdown.
   */
  Drupal.dateYearRange.SelectListWithCustomOption.prototype.syncTextfield = function () {
    var value = this.$dropdown.val();
    this.$textfield.val(value);
  };

})(jQuery);
