<!-- The <detail-list-sk> custom element declaration.

    Manages a list of child elements like digest-detail-sk
    that produce zoom-clicked, triage and commit-info events.

    Handles the events and also focus highlighting.
    It also responds to keyboard shortcuts. Since keyboard events
    are registered against the global 'document' object, it provides
    the 'startUse' and 'endUse' functions to indicate when this element
    is active. This is particularly important if it's part of dynamic
    behavior like pop-up dialogs.

    Attributes:
      None

    Events:
      None

    Methods:
      startUse - to be called before the element is actively being used.
                 It registers the necessary keyboard shortcuts.

      endUse - to be called once the element is not used any more.

      openHelpDialog - opens the help dialog for key bindings.
-->

<link rel="import" href="help-dialog-sk.html">

<dom-module id="detail-list-sk">
  <template>
    <content></content>

    <!-- help dialog -->
    <help-dialog-sk id="helpDialog">
      <table>
        <tr><th colspan=2>Keyboard Shortcuts</th></tr>
        <tr><th>J</th><td>Next</td></tr>
        <tr><th>K</th><td>Prev</td></tr>
        <tr><th>W</th><td>Zoom</td></tr>
        <tr><th>A</th><td>Postive</td></tr>
        <tr><th>S</th><td>Negative</td></tr>
        <tr><th>D</th><td>Untriaged</td></tr>
        <tr><th>?</th><td>Help</td></tr>
      </table>
    </help-dialog-sk>
  </template>
  <script>
    Polymer({
      is: 'detail-list-sk',

      ready: function () {
        this.listen(this, 'zoom-dialog-opened', '_handleZoomOpened');
        this.listen(this, 'zoom-dialog-closed', '_handleZoomClosed');
      },

      startUse: function() {
        this.listen(document, 'keypress', '_handleKeyDown');
      },

      endUse: function() {
        this.unlisten(document, 'keypress', '_handleKeyDown');
      },

      openHelpDialog: function() {
        this.$.helpDialog.open();
      },

      _handleKeyDown: function(e) {
        if (this._zooming) {
          return;
        }

        var c = String.fromCharCode(e.keyCode).toUpperCase();
        switch (c) {
          case 'J':
            this._focusNext();
            break;
          case 'K':
            this._focusPrev();
            break;
          case 'A':
            this._markFocus('positive');
            break;
          case 'S':
            this._markFocus('negative');
            break;
          case 'D':
            this._markFocus('untriaged');
            break;
          case 'W':
            this._zoomIn();
            break;
          case '?':
            this.openHelpDialog();
            break;
        }
      },

      _handleZoomClosed: function () {
       this._zooming = false;
      },

      _handleZoomOpened: function () {
        this._zooming = true;
      },

      // _findFocus returns the current details element with the keyboard focus.
      _findFocus: function () {
          return $$$('[data-focus]', this);
      },

      // _moveFocus does the actual work of changing the focus from lastEle
      // to nextEle.
      _moveFocus: function (lastEle, nextEle) {
        // Don't wrap around past the bottom of the list.
        if (lastEle != null && nextEle == null) {
          return;
        }

        if (lastEle != null) {
          Polymer.dom(lastEle).removeAttribute('data-focus');
        }

        // If nothing is selected, then focus on the first details element.
        if (nextEle == null) {
          nextEle = Polymer.dom(this).firstElementChild;
        }

        Polymer.dom(nextEle).setAttribute('data-focus', 'true');
        nextEle.scrollIntoView(true);
      },

      _focusSet: function (ele) {
        var lastEle = this._findFocus();
        this._moveFocus(lastEle, ele);
      },

      // Move the focus to the next digest.
      _focusNext: function () {
        var nextEle = null;
        var lastEle = this._findFocus();

        if (lastEle != null) {
          nextEle = lastEle.nextElementSibling;
          if (nextEle.nodeName == 'TEMPLATE') {
            nextEle = null;
          }
        }
        this._moveFocus(lastEle, nextEle);
      },

      // Move the focus to the previous digest.
      _focusPrev: function () {
        var nextEle = null;
        var lastEle = this._findFocus();

        if (lastEle != null) {
          nextEle = lastEle.previousElementSibling;
        }
        this._moveFocus(lastEle, nextEle);
      },

      _markFocus: function (status) {
        var ele = this._findFocus();
        if (ele && ele.triggerTriage) {
          ele.triggerTriage(status);
        }
      },

      _zoomIn: function () {
        const ele = this._findFocus();
        if (ele) {
          const zoom = $$$('button.zoom_btn', ele);
          zoom && zoom.click();
        }
      }
    });
  </script>
</dom-module>
