<!--
Copyright (C) 2015 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../behaviors/keyboard-shortcut-behavior.html">
<link rel="import" href="../styles/gr-change-list-styles.html">
<link rel="import" href="gr-change-list-item.html">

<dom-module id="gr-change-list">
  <template>
    <style>
      :host {
        display: flex;
        flex-direction: column;
      }
      .headerRow {
        display: flex;
      }
      .topHeader,
      .groupHeader {
        border-bottom: 1px solid #eee;
        font-weight: bold;
        padding: .3em .5em;
      }
      .topHeader {
        background-color: #ddd;
        flex-shrink: 0;
      }
    </style>
    <style include="gr-change-list-styles"></style>
    <div class="headerRow">
      <span class="topHeader keyboard"></span> <!-- keyboard position indicator -->
      <span class="topHeader star" hidden$="[[!showStar]]"></span>
      <span class="topHeader subject">Subject</span>
      <span class="topHeader status">Status</span>
      <span class="topHeader owner">Owner</span>
      <span class="topHeader project">Project</span>
      <span class="topHeader branch">Branch</span>
      <span class="topHeader updated">Updated</span>
      <span class="topHeader size">Size</span>
      <template is="dom-repeat" items="[[labelNames]]" as="labelName">
        <span class="topHeader label" title$="[[labelName]]">
          [[_computeLabelShortcut(labelName)]]
        </span>
      </template>
    </div>
    <template is="dom-repeat" items="{{groups}}" as="changeGroup" index-as="groupIndex">
      <template is="dom-if" if="[[_groupTitle(groupIndex)]]">
        <div class="groupHeader">[[_groupTitle(groupIndex)]]</div>
      </template>
      <template is="dom-repeat" items="[[changeGroup]]" as="change">
        <gr-change-list-item
            selected$="[[_computeItemSelected(index, groupIndex, selectedIndex)]]"
            change="[[change]]"
            show-star="[[showStar]]"
            label-names="[[labelNames]]"></gr-change-list-item>
      </template>
    </template>
  </template>

  <script>
  (function() {
    'use strict';

    Polymer({
      is: 'gr-change-list',

      hostAttributes: {
        tabindex: 0,
      },

      properties: {
        /**
         * An array of ChangeInfo objects to render.
         * https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-info
         */
        changes: {
          type: Array,
          observer: '_changesChanged',
        },
        /**
         * ChangeInfo objects grouped into arrays. The groups and changes
         * properties should not be used together.
         */
        groups: {
          type: Array,
          value: function() { return []; },
        },
        groupTitles: {
          type: Array,
          value: function() { return []; },
        },
        labelNames: {
          type: Array,
          computed: '_computeLabelNames(groups)',
        },
        selectedIndex: {
          type: Number,
          notify: true,
        },
        showStar: {
          type: Boolean,
          value: false,
        },
        keyEventTarget: {
          type: Object,
          value: function() { return document.body; },
        },
      },

      behaviors: [ Gerrit.KeyboardShortcutBehavior ],

      _computeLabelNames: function(groups) {
        var labels = [];
        var nonExistingLabel = function(item) {
          return labels.indexOf(item) < 0;
        };
        for (var i = 0; i < groups.length; i++) {
          var group = groups[i];
          for (var j = 0; j < group.length; j++) {
            var change = group[j];
            if (!change.labels) { continue; }
            var currentLabels = Object.keys(change.labels);
            labels = labels.concat(currentLabels.filter(nonExistingLabel));
          }
        }
        return labels.sort();
      },

      _computeLabelShortcut: function(labelName) {
        return labelName.replace(/[a-z-]/g, '');
      },

      _changesChanged: function(changes) {
        this.groups = [changes];
      },

      _groupTitle: function(groupIndex) {
        if (groupIndex > this.groupTitles.length - 1) { return null; }
        return this.groupTitles[groupIndex];
      },

      _computeItemSelected: function(index, groupIndex, selectedIndex) {
        var idx = 0;
        for (var i = 0; i < groupIndex; i++) {
          idx += this.groups[i].length;
        }
        idx += index;
        return idx == selectedIndex;
      },

      _handleKey: function(e) {
        if (this.shouldSupressKeyboardShortcut(e)) { return; }

        if (this.groups == null) { return; }
        var len = 0;
        this.groups.forEach(function(group) {
          len += group.length;
        });
        switch(e.keyCode) {
          case 74:  // 'j'
            e.preventDefault();
            if (this.selectedIndex == len - 1) { return; }
            this.selectedIndex += 1;
            break;
          case 75:  // 'k'
            e.preventDefault();
            if (this.selectedIndex == 0) { return; }
            this.selectedIndex -= 1;
            break;
          case 79:  // 'o'
          case 13:  // 'enter'
            e.preventDefault();
            page.show(this._changeURLForIndex(this.selectedIndex));
            break;
        }
      },

      _changeURLForIndex: function(index) {
        var changeEls = this._getListItems();
        if (index < changeEls.length && changeEls[index]) {
          return changeEls[index].changeURL;
        }
        return '';
      },

      _getListItems: function() {
        return Polymer.dom(this.root).querySelectorAll('gr-change-list-item');
      },

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