/**
 * @license
 * 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.
 */
import '../../../behaviors/base-url-behavior/base-url-behavior.js';

import '../../../behaviors/gr-change-table-behavior/gr-change-table-behavior.js';
import '../../../behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior.js';
import '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
import '../../../scripts/bundled-polymer.js';
import '../../../behaviors/fire-behavior/fire-behavior.js';
import '../../../styles/gr-change-list-styles.js';
import '../../core/gr-navigation/gr-navigation.js';
import '../../shared/gr-cursor-manager/gr-cursor-manager.js';
import '../gr-change-list-item/gr-change-list-item.js';
import '../../../styles/shared-styles.js';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-change-list_html.js';

const NUMBER_FIXED_COLUMNS = 3;
const CLOSED_STATUS = ['MERGED', 'ABANDONED'];
const LABEL_PREFIX_INVALID_PROLOG = 'Invalid-Prolog-Rules-Label-Name--';
const MAX_SHORTCUT_CHARS = 5;

/**
 * @appliesMixin Gerrit.BaseUrlMixin
 * @appliesMixin Gerrit.ChangeTableMixin
 * @appliesMixin Gerrit.FireMixin
 * @appliesMixin Gerrit.KeyboardShortcutMixin
 * @appliesMixin Gerrit.RESTClientMixin
 * @appliesMixin Gerrit.URLEncodingMixin
 * @extends Polymer.Element
 */
class GrChangeList extends mixinBehaviors( [
  Gerrit.BaseUrlBehavior,
  Gerrit.ChangeTableBehavior,
  Gerrit.FireBehavior,
  Gerrit.KeyboardShortcutBehavior,
  Gerrit.RESTClientBehavior,
  Gerrit.URLEncodingBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-change-list'; }
  /**
   * Fired when next page key shortcut was pressed.
   *
   * @event next-page
   */

  /**
   * Fired when previous page key shortcut was pressed.
   *
   * @event previous-page
   */

  static get properties() {
    return {
    /**
     * The logged-in user's account, or an empty object if no user is logged
     * in.
     */
      account: {
        type: Object,
        value: null,
      },
      /**
       * 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 sections and changes
       * properties should not be used together.
       *
       * @type {!Array<{
       *   name: string,
       *   query: string,
       *   results: !Array<!Object>
       * }>}
       */
      sections: {
        type: Array,
        value() { return []; },
      },
      labelNames: {
        type: Array,
        computed: '_computeLabelNames(sections)',
      },
      _dynamicHeaderEndpoints: {
        type: Array,
      },
      selectedIndex: {
        type: Number,
        notify: true,
      },
      showNumber: Boolean, // No default value to prevent flickering.
      showStar: {
        type: Boolean,
        value: false,
      },
      showReviewedState: {
        type: Boolean,
        value: false,
      },
      keyEventTarget: {
        type: Object,
        value() { return document.body; },
      },
      changeTableColumns: Array,
      visibleChangeTableColumns: Array,
      preferences: Object,
    };
  }

  static get observers() {
    return [
      '_sectionsChanged(sections.*)',
      '_computePreferences(account, preferences)',
    ];
  }

  keyboardShortcuts() {
    return {
      [this.Shortcut.CURSOR_NEXT_CHANGE]: '_nextChange',
      [this.Shortcut.CURSOR_PREV_CHANGE]: '_prevChange',
      [this.Shortcut.NEXT_PAGE]: '_nextPage',
      [this.Shortcut.PREV_PAGE]: '_prevPage',
      [this.Shortcut.OPEN_CHANGE]: '_openChange',
      [this.Shortcut.TOGGLE_CHANGE_REVIEWED]: '_toggleChangeReviewed',
      [this.Shortcut.TOGGLE_CHANGE_STAR]: '_toggleChangeStar',
      [this.Shortcut.REFRESH_CHANGE_LIST]: '_refreshChangeList',
    };
  }

  /** @override */
  created() {
    super.created();
    this.addEventListener('keydown',
        e => this._scopedKeydownHandler(e));
  }

  /** @override */
  ready() {
    super.ready();
    this._ensureAttribute('tabindex', 0);
  }

  /** @override */
  attached() {
    super.attached();
    Gerrit.awaitPluginsLoaded().then(() => {
      this._dynamicHeaderEndpoints = Gerrit._endpoints.getDynamicEndpoints(
          'change-list-header');
    });
  }

  /**
   * Iron-a11y-keys-behavior catches keyboard events globally. Some keyboard
   * events must be scoped to a component level (e.g. `enter`) in order to not
   * override native browser functionality.
   *
   * Context: Issue 7294
   */
  _scopedKeydownHandler(e) {
    if (e.keyCode === 13) {
      // Enter.
      this._openChange(e);
    }
  }

  _lowerCase(column) {
    return column.toLowerCase();
  }

  _computePreferences(account, preferences) {
    // Polymer 2: check for undefined
    if ([account, preferences].some(arg => arg === undefined)) {
      return;
    }

    this.changeTableColumns = this.columnNames;

    if (account) {
      this.showNumber = !!(preferences &&
          preferences.legacycid_in_change_table);
      if (preferences.change_table &&
          preferences.change_table.length > 0) {
        this.visibleChangeTableColumns =
          this.getVisibleColumns(preferences.change_table);
      } else {
        this.visibleChangeTableColumns = this.columnNames;
      }
    } else {
      // Not logged in.
      this.showNumber = false;
      this.visibleChangeTableColumns = this.columnNames;
    }
  }

  _computeColspan(changeTableColumns, labelNames) {
    if (!changeTableColumns || !labelNames) return;
    return changeTableColumns.length + labelNames.length +
        NUMBER_FIXED_COLUMNS;
  }

  _computeLabelNames(sections) {
    if (!sections) { return []; }
    let labels = [];
    const nonExistingLabel = function(item) {
      return !labels.includes(item);
    };
    for (const section of sections) {
      if (!section.results) { continue; }
      for (const change of section.results) {
        if (!change.labels) { continue; }
        const currentLabels = Object.keys(change.labels);
        labels = labels.concat(currentLabels.filter(nonExistingLabel));
      }
    }
    return labels.sort();
  }

  _computeLabelShortcut(labelName) {
    if (labelName.startsWith(LABEL_PREFIX_INVALID_PROLOG)) {
      labelName = labelName.slice(LABEL_PREFIX_INVALID_PROLOG.length);
    }
    return labelName.split('-')
        .reduce((a, i) => {
          if (!i) { return a; }
          return a + i[0].toUpperCase();
        }, '')
        .slice(0, MAX_SHORTCUT_CHARS);
  }

  _changesChanged(changes) {
    this.sections = changes ? [{results: changes}] : [];
  }

  _processQuery(query) {
    let tokens = query.split(' ');
    const invalidTokens = ['limit:', 'age:', '-age:'];
    tokens = tokens.filter(token => !invalidTokens
        .some(invalidToken => token.startsWith(invalidToken)));
    return tokens.join(' ');
  }

  _sectionHref(query) {
    return Gerrit.Nav.getUrlForSearchQuery(this._processQuery(query));
  }

  /**
   * Maps an index local to a particular section to the absolute index
   * across all the changes on the page.
   *
   * @param {number} sectionIndex index of section
   * @param {number} localIndex index of row within section
   * @return {number} absolute index of row in the aggregate dashboard
   */
  _computeItemAbsoluteIndex(sectionIndex, localIndex) {
    let idx = 0;
    for (let i = 0; i < sectionIndex; i++) {
      idx += this.sections[i].results.length;
    }
    return idx + localIndex;
  }

  _computeItemSelected(sectionIndex, index, selectedIndex) {
    const idx = this._computeItemAbsoluteIndex(sectionIndex, index);
    return idx == selectedIndex;
  }

  _computeItemNeedsReview(account, change, showReviewedState) {
    return showReviewedState && !change.reviewed &&
        !change.work_in_progress &&
        this.changeIsOpen(change) &&
        (!account || account._account_id != change.owner._account_id);
  }

  _computeItemHighlight(account, change) {
    // Do not show the assignee highlight if the change is not open.
    if (!change ||!change.assignee ||
        !account ||
        CLOSED_STATUS.indexOf(change.status) !== -1) {
      return false;
    }
    return account._account_id === change.assignee._account_id;
  }

  _nextChange(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e)) { return; }

    e.preventDefault();
    this.$.cursor.next();
  }

  _prevChange(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e)) { return; }

    e.preventDefault();
    this.$.cursor.previous();
  }

  _openChange(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e)) { return; }

    e.preventDefault();
    Gerrit.Nav.navigateToChange(this._changeForIndex(this.selectedIndex));
  }

  _nextPage(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e) && !this.isModifierPressed(e, 'shiftKey')) {
      return;
    }

    e.preventDefault();
    this.fire('next-page');
  }

  _prevPage(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e) && !this.isModifierPressed(e, 'shiftKey')) {
      return;
    }

    e.preventDefault();
    this.fire('previous-page');
  }

  _toggleChangeReviewed(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e)) { return; }

    e.preventDefault();
    this._toggleReviewedForIndex(this.selectedIndex);
  }

  _toggleReviewedForIndex(index) {
    const changeEls = this._getListItems();
    if (index >= changeEls.length || !changeEls[index]) {
      return;
    }

    const changeEl = changeEls[index];
    changeEl.toggleReviewed();
  }

  _refreshChangeList(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }

    e.preventDefault();
    this._reloadWindow();
  }

  _reloadWindow() {
    window.location.reload();
  }

  _toggleChangeStar(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e)) { return; }

    e.preventDefault();
    this._toggleStarForIndex(this.selectedIndex);
  }

  _toggleStarForIndex(index) {
    const changeEls = this._getListItems();
    if (index >= changeEls.length || !changeEls[index]) {
      return;
    }

    const changeEl = changeEls[index];
    changeEl.shadowRoot
        .querySelector('gr-change-star').toggleStar();
  }

  _changeForIndex(index) {
    const changeEls = this._getListItems();
    if (index < changeEls.length && changeEls[index]) {
      return changeEls[index].change;
    }
    return null;
  }

  _getListItems() {
    return Array.from(
        dom(this.root).querySelectorAll('gr-change-list-item'));
  }

  _sectionsChanged() {
    // Flush DOM operations so that the list item elements will be loaded.
    afterNextRender(this, () => {
      this.$.cursor.stops = this._getListItems();
      this.$.cursor.moveToStart();
    });
  }

  _isOutgoing(section) {
    return !!section.isOutgoing;
  }

  _isEmpty(section) {
    return !section.results.length;
  }
}

customElements.define(GrChangeList.is, GrChangeList);
