<!-- The <select-popup-sk> custom element declaration.

  Displays a button that opens a popup dialog with a list of checkboxes.

  Attributes:
    None

  Events:
    changed-selection: This fired when the selection changed. The detail
                       field contains the new selection as an array of strings.

  Methods:
    setParamSet(params): Takes the set of parameters to draw from. 'set' is in
                         the same format as returned by the /json/paramset endpoint.

    setSelection(sel): Sets the current selection. 'sel' is an array of strings.
                       Must be called after setParamSet.

-->
<link rel="import" href="bower_components/paper-button/paper-button.html">
<link rel="import" href="bower_components/paper-dialog/paper-dialog.html">
<link rel="import" href="bower_components/paper-dialog-scrollable/paper-dialog-scrollable.html">
<link rel="import" href="bower_components/paper-checkbox/paper-checkbox.html">
<link rel="import" href="bower_components/iron-icons/iron-icons.html">
<link rel="import" href="shared-styles.html">

<dom-module id="select-popup-sk">
  <template>
    <style include="shared-styles">
      .asc #asc {
        display: inline-block;
      }
      .desc #desc {
        display: inline-block;
      }
      #asc,
      #desc {
        display: none;
      }

      .checkboxItem {
        margin: 0.5em;
      }

    </style>

    <paper-button id="paramsSelectionButton" on-tap="_toggleButtonHandler" toggles raised disabled="{{_open}}">
       <iron-icon icon="[[icon]]" hidden$="{{!_syncParams}}"></iron-icon>
    </paper-button>
    <array-selector id="arrSelector" items="{{_items}}" selected="{{selected}}" multi toggle></array-selector>
    <paper-dialog id="paramsSelectionDialog" with-backdrop>
      <paper-dialog-scrollable>
          <template is='dom-repeat' items='{{ _items }}'>
            <div class="checkboxItem">
              <paper-checkbox checked="{{ item.checked }}">
                  {{ item.name }}
              </paper-checkbox>
            </div>
          </template>
      </paper-dialog-scrollable>
      <div>
        <paper-button raised dialog-dismiss>Cancel</paper-button>
        <paper-button id="doneButton" raised dialog-dismiss>Done</paper-button>
      </div>
    </paper-dialog>
  </template>
  <script>
    Polymer({
      is: 'select-popup-sk',

      properties: {
        icon: {
          type: String,
          value: "icons:menu"
        },
        _items: {
          type: Array,
          value: function() { return []; },
          notify: true
        },
        _selLookup: {
          type: Object,
          value: function() { return {}; }
        },
        _open : {
          type: Boolean,
          value: false
        }
      },

      ready: function () {
        this._currSelection = [];
        var dialog = this.$.paramsSelectionDialog;
        this.listen(this.$.doneButton, 'tap', '_doneHandler');
        this.listen(dialog, 'iron-overlay-closed', '_closedHandler');
        dialog.positionTarget = this.$.paramsSelectionButton;
        dialog.refit();
      },

      setSelection: function(selection) {
        var sel = {};
        for(var i = 0, ilen = selection.length; i < ilen; i++) {
          sel[selection[i]] = true;
        }
        this._selLookup = sel;
        this._syncChecked();
      },

      setParamSet: function(paramSet) {
        var keys = Object.keys(paramSet).sort();
        var items = [];
        for(var i=0, ilen=keys.length; i < ilen; i++) {
          items.push({
            name: keys[i],
            checked: false
          })
        }
        this._items = items;
        this._syncChecked();
      },

      _syncChecked: function() {
        for(var i=0, ilen=this._items.length; i < ilen; i++) {
          this.set("_items." + i + ".checked", !!this._selLookup[this._items[i].name]);
        }
        this._currSelection = this._getSelection();
      },

      _getSelection: function() {
        var cur = [];
        for(var i=0, ilen=this._items.length; i<ilen; i++) {
          if (this._items[i].checked) {
            cur.push(this._items[i].name);
          }
        }
        return cur;
      },

      _toggleButtonHandler: function(ev) {
        this.set("_open", true);
        this.$.paramsSelectionDialog.open();
      },

      _doneHandler: function(ev) {
        var sel = this._getSelection();
        if (!sk.array.equal(sel, this._currSelection)) {
          this._currSelection = sel;
          this.fire('changed-selection', sel);
        }
      },

      _closedHandler: function(ev) {
        ev.stopPropagation();
        this.async(function(){
          this.setSelection(this._currSelection);
        });
        this.set("_open", false);
      }
    });
  </script>
</dom-module>
