// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('options', function() {
  /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel;
  /** @const */ var DeletableItem = options.DeletableItem;
  /** @const */ var DeletableItemList = options.DeletableItemList;
  /** @const */ var List = cr.ui.List;
  /** @const */ var ListItem = cr.ui.ListItem;
  /** @const */ var ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;

  /**
   * Creates a new Language list item.
   * @param {Object} languageInfo The information of the language.
   * @constructor
   * @extends {DeletableItem.ListItem}
   */
  function LanguageListItem(languageInfo) {
    var el = cr.doc.createElement('li');
    el.__proto__ = LanguageListItem.prototype;
    el.language_ = languageInfo;
    el.decorate();
    return el;
  };

  LanguageListItem.prototype = {
    __proto__: DeletableItem.prototype,

    /**
     * The language code of this language.
     * @type {string}
     * @private
     */
    languageCode_: null,

    /** @override */
    decorate: function() {
      DeletableItem.prototype.decorate.call(this);

      var languageCode = this.language_.code;
      var languageOptions = options.LanguageOptions.getInstance();
      this.deletable = languageOptions.languageIsDeletable(languageCode);
      this.languageCode = languageCode;
      this.languageName = cr.doc.createElement('div');
      this.languageName.className = 'language-name';
      this.languageName.dir = this.language_.textDirection;
      this.languageName.textContent = this.language_.displayName;
      this.contentElement.appendChild(this.languageName);
      this.title = this.language_.nativeDisplayName;
      this.draggable = true;
    },
  };

  /**
   * Creates a new language list.
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {cr.ui.List}
   */
  var LanguageList = cr.ui.define('list');

  /**
   * Gets information of a language from the given language code.
   * @param {string} languageCode Language code (ex. "fr").
   */
  LanguageList.getLanguageInfoFromLanguageCode = function(languageCode) {
    // Build the language code to language info dictionary at first time.
    if (!this.languageCodeToLanguageInfo_) {
      this.languageCodeToLanguageInfo_ = {};
      var languageList = loadTimeData.getValue('languageList');
      for (var i = 0; i < languageList.length; i++) {
        var languageInfo = languageList[i];
        this.languageCodeToLanguageInfo_[languageInfo.code] = languageInfo;
      }
    }

    return this.languageCodeToLanguageInfo_[languageCode];
  }

  /**
   * Returns true if the given language code is valid.
   * @param {string} languageCode Language code (ex. "fr").
   */
  LanguageList.isValidLanguageCode = function(languageCode) {
    // Having the display name for the language code means that the
    // language code is valid.
    if (LanguageList.getLanguageInfoFromLanguageCode(languageCode)) {
      return true;
    }
    return false;
  }

  LanguageList.prototype = {
    __proto__: DeletableItemList.prototype,

    // The list item being dragged.
    draggedItem: null,
    // The drop position information: "below" or "above".
    dropPos: null,
    // The preference is a CSV string that describes preferred languages
    // in Chrome OS. The language list is used for showing the language
    // list in "Language and Input" options page.
    preferredLanguagesPref: 'settings.language.preferred_languages',
    // The preference is a CSV string that describes accept languages used
    // for content negotiation. To be more precise, the list will be used
    // in "Accept-Language" header in HTTP requests.
    acceptLanguagesPref: 'intl.accept_languages',

    /** @override */
    decorate: function() {
      DeletableItemList.prototype.decorate.call(this);
      this.selectionModel = new ListSingleSelectionModel;

      // HACK(arv): http://crbug.com/40902
      window.addEventListener('resize', this.redraw.bind(this));

      // Listen to pref change.
      if (cr.isChromeOS) {
        Preferences.getInstance().addEventListener(this.preferredLanguagesPref,
            this.handlePreferredLanguagesPrefChange_.bind(this));
      } else {
        Preferences.getInstance().addEventListener(this.acceptLanguagesPref,
            this.handleAcceptLanguagesPrefChange_.bind(this));
      }

      // Listen to drag and drop events.
      this.addEventListener('dragstart', this.handleDragStart_.bind(this));
      this.addEventListener('dragenter', this.handleDragEnter_.bind(this));
      this.addEventListener('dragover', this.handleDragOver_.bind(this));
      this.addEventListener('drop', this.handleDrop_.bind(this));
      this.addEventListener('dragleave', this.handleDragLeave_.bind(this));
    },

    createItem: function(languageCode) {
      languageInfo = LanguageList.getLanguageInfoFromLanguageCode(languageCode);
      return new LanguageListItem(languageInfo);
    },

    /*
     * For each item, determines whether it's deletable.
     */
    updateDeletable: function() {
      var items = this.items;
      for (var i = 0; i < items.length; ++i) {
        var item = items[i];
        var languageCode = item.languageCode;
        var languageOptions = options.LanguageOptions.getInstance();
        item.deletable = languageOptions.languageIsDeletable(languageCode);
      }
    },

    /*
     * Adds a language to the language list.
     * @param {string} languageCode language code (ex. "fr").
     */
    addLanguage: function(languageCode) {
      // It shouldn't happen but ignore the language code if it's
      // null/undefined, or already present.
      if (!languageCode || this.dataModel.indexOf(languageCode) >= 0) {
        return;
      }
      this.dataModel.push(languageCode);
      // Select the last item, which is the language added.
      this.selectionModel.selectedIndex = this.dataModel.length - 1;

      this.savePreference_();
    },

    /*
     * Gets the language codes of the currently listed languages.
     */
    getLanguageCodes: function() {
      return this.dataModel.slice();
    },

    /*
     * Clears the selection
     */
    clearSelection: function() {
      this.selectionModel.unselectAll();
    },

    /*
     * Gets the language code of the selected language.
     */
    getSelectedLanguageCode: function() {
      return this.selectedItem;
    },

    /*
     * Selects the language by the given language code.
     * @returns {boolean} True if the operation is successful.
     */
    selectLanguageByCode: function(languageCode) {
      var index = this.dataModel.indexOf(languageCode);
      if (index >= 0) {
        this.selectionModel.selectedIndex = index;
        return true;
      }
      return false;
    },

    /** @override */
    deleteItemAtIndex: function(index) {
      if (index >= 0) {
        this.dataModel.splice(index, 1);
        // Once the selected item is removed, there will be no selected item.
        // Select the item pointed by the lead index.
        index = this.selectionModel.leadIndex;
        this.savePreference_();
      }
      return index;
    },

    /*
     * Computes the target item of drop event.
     * @param {Event} e The drop or dragover event.
     * @private
     */
    getTargetFromDropEvent_: function(e) {
      var target = e.target;
      // e.target may be an inner element of the list item
      while (target != null && !(target instanceof ListItem)) {
        target = target.parentNode;
      }
      return target;
    },

    /*
     * Handles the dragstart event.
     * @param {Event} e The dragstart event.
     * @private
     */
    handleDragStart_: function(e) {
      var target = e.target;
      // ListItem should be the only draggable element type in the page,
      // but just in case.
      if (target instanceof ListItem) {
        this.draggedItem = target;
        e.dataTransfer.effectAllowed = 'move';
        // We need to put some kind of data in the drag or it will be
        // ignored.  Use the display name in case the user drags to a text
        // field or the desktop.
        e.dataTransfer.setData('text/plain', target.title);
      }
    },

    /*
     * Handles the dragenter event.
     * @param {Event} e The dragenter event.
     * @private
     */
    handleDragEnter_: function(e) {
      e.preventDefault();
    },

    /*
     * Handles the dragover event.
     * @param {Event} e The dragover event.
     * @private
     */
    handleDragOver_: function(e) {
      var dropTarget = this.getTargetFromDropEvent_(e);
      // Determines whether the drop target is to accept the drop.
      // The drop is only successful on another ListItem.
      if (!(dropTarget instanceof ListItem) ||
          dropTarget == this.draggedItem) {
        this.hideDropMarker_();
        return;
      }
      // Compute the drop postion. Should we move the dragged item to
      // below or above the drop target?
      var rect = dropTarget.getBoundingClientRect();
      var dy = e.clientY - rect.top;
      var yRatio = dy / rect.height;
      var dropPos = yRatio <= .5 ? 'above' : 'below';
      this.dropPos = dropPos;
      this.showDropMarker_(dropTarget, dropPos);
      e.preventDefault();
    },

    /*
     * Handles the drop event.
     * @param {Event} e The drop event.
     * @private
     */
    handleDrop_: function(e) {
      var dropTarget = this.getTargetFromDropEvent_(e);
      this.hideDropMarker_();

      // Delete the language from the original position.
      var languageCode = this.draggedItem.languageCode;
      var originalIndex = this.dataModel.indexOf(languageCode);
      this.dataModel.splice(originalIndex, 1);
      // Insert the language to the new position.
      var newIndex = this.dataModel.indexOf(dropTarget.languageCode);
      if (this.dropPos == 'below')
        newIndex += 1;
      this.dataModel.splice(newIndex, 0, languageCode);
      // The cursor should move to the moved item.
      this.selectionModel.selectedIndex = newIndex;
      // Save the preference.
      this.savePreference_();
    },

    /*
     * Handles the dragleave event.
     * @param {Event} e The dragleave event
     * @private
     */
    handleDragLeave_: function(e) {
      this.hideDropMarker_();
    },

    /*
     * Shows and positions the marker to indicate the drop target.
     * @param {HTMLElement} target The current target list item of drop
     * @param {string} pos 'below' or 'above'
     * @private
     */
    showDropMarker_: function(target, pos) {
      window.clearTimeout(this.hideDropMarkerTimer_);
      var marker = $('language-options-list-dropmarker');
      var rect = target.getBoundingClientRect();
      var markerHeight = 8;
      if (pos == 'above') {
        marker.style.top = (rect.top - markerHeight / 2) + 'px';
      } else {
        marker.style.top = (rect.bottom - markerHeight / 2) + 'px';
      }
      marker.style.width = rect.width + 'px';
      marker.style.left = rect.left + 'px';
      marker.style.display = 'block';
    },

    /*
     * Hides the drop marker.
     * @private
     */
    hideDropMarker_: function() {
      // Hide the marker in a timeout to reduce flickering as we move between
      // valid drop targets.
      window.clearTimeout(this.hideDropMarkerTimer_);
      this.hideDropMarkerTimer_ = window.setTimeout(function() {
        $('language-options-list-dropmarker').style.display = '';
      }, 100);
    },

    /**
     * Handles preferred languages pref change.
     * @param {Event} e The change event object.
     * @private
     */
    handlePreferredLanguagesPrefChange_: function(e) {
      var languageCodesInCsv = e.value.value;
      var languageCodes = languageCodesInCsv.split(',');

      // Add the UI language to the initial list of languages.  This is to avoid
      // a bug where the UI language would be removed from the preferred
      // language list by sync on first login.
      // See: crosbug.com/14283
      languageCodes.push(navigator.language);
      languageCodes = this.filterBadLanguageCodes_(languageCodes);
      this.load_(languageCodes);
    },

    /**
     * Handles accept languages pref change.
     * @param {Event} e The change event object.
     * @private
     */
    handleAcceptLanguagesPrefChange_: function(e) {
      var languageCodesInCsv = e.value.value;
      var languageCodes = this.filterBadLanguageCodes_(
          languageCodesInCsv.split(','));
      this.load_(languageCodes);
    },

    /**
     * Loads given language list.
     * @param {Array} languageCodes List of language codes.
     * @private
     */
    load_: function(languageCodes) {
      // Preserve the original selected index. See comments below.
      var originalSelectedIndex = (this.selectionModel ?
                                   this.selectionModel.selectedIndex : -1);
      this.dataModel = new ArrayDataModel(languageCodes);
      if (originalSelectedIndex >= 0 &&
          originalSelectedIndex < this.dataModel.length) {
        // Restore the original selected index if the selected index is
        // valid after the data model is loaded. This is neeeded to keep
        // the selected language after the languge is added or removed.
        this.selectionModel.selectedIndex = originalSelectedIndex;
        // The lead index should be updated too.
        this.selectionModel.leadIndex = originalSelectedIndex;
      } else if (this.dataModel.length > 0) {
        // Otherwise, select the first item if it's not empty.
        // Note that ListSingleSelectionModel won't select an item
        // automatically, hence we manually select the first item here.
        this.selectionModel.selectedIndex = 0;
      }
    },

    /**
     * Saves the preference.
     */
    savePreference_: function() {
      chrome.send('updateLanguageList', [this.dataModel.slice()]);
      cr.dispatchSimpleEvent(this, 'save');
    },

    /**
     * Filters bad language codes in case bad language codes are
     * stored in the preference. Removes duplicates as well.
     * @param {Array} languageCodes List of language codes.
     * @private
     */
    filterBadLanguageCodes_: function(languageCodes) {
      var filteredLanguageCodes = [];
      var seen = {};
      for (var i = 0; i < languageCodes.length; i++) {
        // Check if the the language code is valid, and not
        // duplicate. Otherwise, skip it.
        if (LanguageList.isValidLanguageCode(languageCodes[i]) &&
            !(languageCodes[i] in seen)) {
          filteredLanguageCodes.push(languageCodes[i]);
          seen[languageCodes[i]] = true;
        }
      }
      return filteredLanguageCodes;
    },
  };

  return {
    LanguageList: LanguageList,
    LanguageListItem: LanguageListItem
  };
});
