<!-- The <commands-sk> custom element declaration.

  Displays the list of commands in an SKP in an ordered list.

  Attributes:
    cmd - The data to display. Looks like:

      {
        "version": 1,
        "commands":[
          {
            "details": {"command":"BeginDrawPicture"},
            "_depth":0,
            "_prefix":[]
          },
          {
            "details":{"command":"Save"},
            "_depth":1,
            "_prefix":[{"icon":"image:image","color":"#A6CEE3"}]
          },
          ...
        ]
      }

    item - The index of the command that is selected.

    grouping - The number of op-sks to group together under each
      op-expando-sk.

  Events:
    op-selected - This event contains the index of the op selected in
         e.details.index.

    op-toggled - This event is sent when a paper-checkbox is toggled.
        The checked status and index of the op are returned in e.detail.

        {
          checked: false,
          index: 102,
        }

        This event bubbles up from the op-sk child elements.

  Methods:

     scrollToTop(index) - Scroll the op at the given index to the top of the
       selection.
-->
<style type="text/css" media="screen">
  #selector details-sk.selected {
    background: #eee;
  }
</style>

<link rel=import href="op.html">
<link rel=import href="op-expando.html">
<dom-module id="commands-sk">
  <style>
    :host {
      position: relative;
    }

    #selector {
      overflow-y: scroll;
      height: 79vh;
      display: block;
    }

  </style>
  <template>
    <div id=selector>
      <template is="dom-repeat" items="{{_initial(cmd, grouping)}}" as="command">
        <op-sk op="{{command}}" prefix="{{command._prefix}}" index="{{command._index}}"></op-sk>
      </template>
      <template is="dom-repeat" items="{{_groupings(cmd, grouping)}}" as="g" initial-count="{{grouping}}">
        <op-expando-sk cmd="{{cmd}}" begin="{{g.begin}}" end="{{g.end}}"></op-expando-sk>
      </template>
      <template is="dom-repeat" items="{{_remainder(cmd, grouping)}}" as="command">
        <op-sk op="{{command}}" prefix="{{command._prefix}}" index="{{command._index}}"></op-sk>
      </template>
    </div>
  </template>
</dom-module>

<script>
  Polymer({
    is: "commands-sk",

    properties: {
      cmd: {
        type: Object,
        value: function() { return { commands: [] }; },
        reflectToAttribute: false,
      },
      item: {
        type: Number,
        value: 0,
        reflectToAttribute: true,
        observer: "_itemChange",
      },
      grouping: {
        type: Number,
        value: 10,
        reflectToAttribute: true,
      },
    },

    ready: function() {
      this.$.selector.addEventListener('click', function(e) {
        // Find the op-sk that was selected and return its index, not
        // the item's location in the list.
        var ele = sk.findParent(e.target, "PAPER-CHECKBOX");
        if (ele != null) {
          return;
        }
        ele = sk.findParent(e.target, "PAPER-ICON-BUTTON");
        if (ele != null) {
          return;
        }
        ele = sk.findParent(e.target, "OP-SK");
        if (ele == null) {
          return;
        }
        this.item = this._findItemFromIndex(ele.index);
      }.bind(this));
    },

    // Scrolls the op-sk with index=index to the top. Waits for the
    // element to exist and not be hidden, both of which might
    // occur if the op-sk is inside an op-expando-sk.
    scrollToTop: function(index) {
      var ele = $$$("op-sk[index='" + index + "']", this.$.selector);
      if (ele && ele.style.display != "none") {
        this.$.selector.scrollTop = ele.offsetTop - 150;
      } else {
        window.setTimeout(this.scrollToTop.bind(this, index), 10);
      }
    },

    _findItemFromIndex: function(index) {
      var item = 0;
      for (var i = 0; i < this.cmd.commands.length ; i++) {
        if (this.cmd.commands[i]._index == index) {
          item = i;
          break;
        }
      }
      return item;
    },

    _itemChange: function(newItem, oldItem) {
      if (this.cmd.commands.length == 0) {
        return;
      }
      var index = this.cmd.commands[this.item]._index;
      if (newItem != oldItem) {
        var detail = {
          index: index,
        }
        this.dispatchEvent(new CustomEvent('op-selected', { detail: detail, bubbles: true }));
      }
      // Unselect the previously selected ele.
      $$("op-sk[selected]", this.$.selector).forEach(function(ele) {
        ele.removeAttribute('selected');
      });
      // Expand the op-expando that contains our new selected ele, if any.
      var begin = Math.floor(this.item/this.grouping)*this.grouping;
      var ele = $$$("op-sk[index='" + index + "']", this.$.selector);
      var expando = $$$("op-expando-sk[begin='" + begin + "']", this.$.selector);
      if (expando && expando.expanded == false) {
        expando.expanded = true;
      }
      // Set the new op-sk as selected.
      this._setSelected(index);
    },

    // Sets the 'selected' attribute of the op-sk with index=index.
    //
    // Will wait for the element to come into existence, which is needed
    // if the op-sk is inside an op-expando-sk.
    _setSelected: function(index) {
      var ele = $$$("op-sk[index='" + index + "']", this.$.selector);
      if (ele) {
        ele.setAttribute('selected', true);
      } else {
        window.setTimeout(this._setSelected.bind(this, index), 10);
      }
    },

    _initial: function(cmd, grouping) {
      return cmd.commands.slice(0, grouping);
    },

    _remainder: function(cmd, grouping) {
      var n = cmd.commands.length;
      if (n <= grouping) {
        return [];
      }
      var remainder = n % grouping;
      return cmd.commands.slice(-remainder);
    },

    _groupings: function(cmd, grouping) {
      var ret = [];
      var n = cmd.commands.length;
      if (n <= grouping) {
        return ret;
      }
      var num_groups = Math.floor(n / grouping) - 1;
      if (num_groups < 1) {
        return ret;
      }
      for (var i = 0; i < num_groups; i++) {
        ret.push({
          begin: (i+1)*grouping,
          end: (i+2)*grouping,
        });
      }
      return ret;
    },

  });
</script>
