<!– @license Copyright © 2015 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at polymer.github.io/LICENSE.txt The complete set of authors may be found at polymer.github.io/AUTHORS.txt The complete set of contributors may be found at polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at polymer.github.io/PATENTS.txt –>

<link rel=“import” href=“../polymer/polymer.html”> <link rel=“import” href=“iron-selectable.html”>

<script>

/** @polymerBehavior Polymer.IronMultiSelectableBehavior */
Polymer.IronMultiSelectableBehaviorImpl = {
  properties: {

    /**
     * If true, multiple selections are allowed.
     */
    multi: {
      type: Boolean,
      value: false,
      observer: 'multiChanged'
    },

    /**
     * Gets or sets the selected elements. This is used instead of `selected` when `multi`
     * is true.
     */
    selectedValues: {
      type: Array,
      notify: true
    },

    /**
     * Returns an array of currently selected items.
     */
    selectedItems: {
      type: Array,
      readOnly: true,
      notify: true
    },

  },

  observers: [
    '_updateSelected(selectedValues.splices)'
  ],

  /**
   * Selects the given value. If the `multi` property is true, then the selected state of the
   * `value` will be toggled; otherwise the `value` will be selected.
   *
   * @method select
   * @param {string|number} value the value to select.
   */
  select: function(value) {
    if (this.multi) {
      if (this.selectedValues) {
        this._toggleSelected(value);
      } else {
        this.selectedValues = [value];
      }
    } else {
      this.selected = value;
    }
  },

  multiChanged: function(multi) {
    this._selection.multi = multi;
  },

  get _shouldUpdateSelection() {
    return this.selected != null ||
      (this.selectedValues != null && this.selectedValues.length);
  },

  _updateAttrForSelected: function() {
    if (!this.multi) {
      Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this);
    } else if (this._shouldUpdateSelection) {
      this.selectedValues = this.selectedItems.map(function(selectedItem) {
        return this._indexToValue(this.indexOf(selectedItem));
      }, this).filter(function(unfilteredValue) {
        return unfilteredValue != null;
      }, this);
    }
  },

  _updateSelected: function() {
    if (this.multi) {
      this._selectMulti(this.selectedValues);
    } else {
      this._selectSelected(this.selected);
    }
  },

  _selectMulti: function(values) {
    if (values) {
      var selectedItems = this._valuesToItems(values);
      // clear all but the current selected items
      this._selection.clear(selectedItems);
      // select only those not selected yet
      for (var i = 0; i < selectedItems.length; i++) {
        this._selection.setItemSelected(selectedItems[i], true);
      }
      // Check for items, since this array is populated only when attached
      if (this.fallbackSelection && this.items.length && !this._selection.get().length) {
        var fallback = this._valueToItem(this.fallbackSelection);
        if (fallback) {
          this.selectedValues = [this.fallbackSelection];
        }
      }
    } else {
      this._selection.clear();
    }
  },

  _selectionChange: function() {
    var s = this._selection.get();
    if (this.multi) {
      this._setSelectedItems(s);
    } else {
      this._setSelectedItems([s]);
      this._setSelectedItem(s);
    }
  },

  _toggleSelected: function(value) {
    var i = this.selectedValues.indexOf(value);
    var unselected = i < 0;
    if (unselected) {
      this.push('selectedValues',value);
    } else {
      this.splice('selectedValues',i,1);
    }
  },

  _valuesToItems: function(values) {
    return (values == null) ? null : values.map(function(value) {
      return this._valueToItem(value);
    }, this);
  }
};

/** @polymerBehavior */
Polymer.IronMultiSelectableBehavior = [
  Polymer.IronSelectableBehavior,
  Polymer.IronMultiSelectableBehaviorImpl
];

</script>