<!-- The <detail-list2-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:
     data - Takes a search.NewSearchResponse describing search results to be
       displayed.

    Events:
      None

    Methods:
      startUse - to be called before the element is atively 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="digest-details2-sk.html">
<link rel="import" href="zoom-dialog-sk.html">
<link rel="import" href="help-dialog-sk.html">

<dom-module id="detail-list2-sk">
  <style type="text/css" media="screen">
    digest-details2-sk {
      display: block;
      box-shadow: 3px 3px 6px 1px rgba(133,133,133,1);
      margin-top: 1em;
      margin-bottom: 1em;
      margin-left: 0;
      margin-right: 0;
      padding-left: 1em;
      padding-top: 1em;
      padding-bottom: 1em;
      padding-right: 0;
    }

    paper-button {
      background: #1F78B4;
      color: white;
    }

    #indexStatus {
      font-weight: bold;
      font-size: 130%;
      margin-left: 2em;
    }
  </style>
  <template>
    <div>
      <paper-button on-tap=_focusFirst title="&lt;" disabled$="[[_isFirst(_index)]]" raised>|&lt;</paper-button>
      <paper-button on-tap=_focusPrev  title="k" disabled$="[[_isFirst(_index)]]" raised>Prev</paper-button>
      <paper-button on-tap=_focusNext  title="j" disabled$="[[_isLast(_index)]]" raised>Next</paper-button>
      <paper-button on-tap=_focusLast  title="&gt;" disabled$="[[_isLast(_index)]]" raised>&gt;|</paper-button>
      <span id=indexStatus>Digest: [[_plusone(_index)]]/[[data.size]]</span>
    </div>

    <digest-details2-sk
      id="digestdetails"
      mode="list"
      triage
      details="[[_item]]"
      commits="[[data.commits]]"
      issue="[[data.issue.id]]">
    </digest-details2-sk>

    <!-- zoom dialog -->
    <zoom-dialog-sk id="detailsZoomDialog"></zoom-dialog-sk>

    <!-- 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>&lt;</th><td>First</td></tr>
        <tr><th>&gt;</th><td>Last</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-list2-sk',

      properties: {
        data: {
          type: Object,
          value: function() {
            return {
              digests: [],
              commits: [],
              issue: null,
              offset: 0,
              size: 0,
            }
          },
          reflectToAttribute: false,
          observer: "_dataChange",
        },
        _item: {
          type: Object,
          value: null,
          reflectToAttribute: false,
        },
      },

      ready: function () {
        this._zooming = false;
        this._index = 0;

        this.listen(this, 'zoom-clicked', "_handleZoomClicked");
        this.listen(this, 'iron-overlay-closed', '_handleZoomClosed');
        this.listen(this, 'triage', '_handleTriage');
      },

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

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

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

      _dataChange: function() {
        this._index = 0;
        if (!this.data || !this.data.digests || this.data.digests.length === 0) {
          return
        }
        this.set('_item', this.data.digests[0]);
      },

      _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 '<':
            this._focusFirst();
            break;
          case '>':
            this._focusLast();
            break;
          case 'A':
            this._markFocus('positive');
            break;
          case 'S':
            this._markFocus('negative');
            break;
          case 'D':
            this._markFocus('untriaged');
            break;
          case 'W':
            this._handleZoomClicked();
            break;
          case '?':
            this.openHelpDialog();
            break;
        }
      },

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

      _handleZoomClicked: function (ev) {
        var zoomDetail;

        // This was triggerd by a keyboard shortcut.
        if (!ev) {
          var ele = this._findFocus();
          if (ele == null) {
            return
          }
          // Extract the zoom information from the element.
          zoomDetail = ele.getZoomDetail();
        } else {
          zoomDetail = ev.detail;
          ev.stopPropagation();
        }

        this.$.detailsZoomDialog.open(zoomDetail);
        this._zooming = true;
      },

      _handleTriage: function (ev) {
        sk.post('/json/triage', JSON.stringify(ev.detail)).catch(sk.errorMessage);
      },

      // _findFocus returns the current details element with the keyboard focus.
      _findFocus: function () {
        return this.$.digestdetails;
      },

      // Move the focus to the next digest.
      _focusNext: function () {
        if (this.data.digests.length === 0) {
          return
        }
        this._index = this._index+1;
        if (this._index >= this.data.digests.length) {
          this._index = this.data.digests.length-1
        }
        this.set('_item', this.data.digests[this._index]);
      },

      // Move the focus to the previous digest.
      _focusPrev: function () {
        if (this.data.digests.length === 0) {
          return
        }
        this._index = this._index-1;
        if (this._index < 0) {
          this._index = 0;
        }
        this.set('_item', this.data.digests[this._index]);
      },

      _focusFirst: function () {
        if (this.data.digests.length === 0) {
          return
        }
        this._index = 0;
        this.set('_item', this.data.digests[this._index]);
      },

      _focusLast: function () {
        if (this.data.digests.length === 0) {
          return
        }
        this._index = this.data.digests.length-1;
        this.set('_item', this.data.digests[this._index]);
      },

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

      _plusone: function(index) {
        return index+1;
      },

      _isFirst: function(index) {
        return index === 0;
      },

      _isLast: function(index) {
        if (this.data.digests) {
          return index === this.data.digests.length-1;
        }
        return true;
      },

    });
  </script>
</dom-module>
