/**
 * @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 '../../../styles/gr-change-list-styles';
import '../../shared/gr-cursor-manager/gr-cursor-manager';
import '../gr-change-list-item/gr-change-list-item';
import '../../../styles/shared-styles';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import {afterNextRender} from '@polymer/polymer/lib/utils/render-status';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-change-list_html';
import {appContext} from '../../../services/app-context';
import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin';
import {
  KeyboardShortcutMixin,
  Shortcut,
  Modifier,
} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {
  GerritNav,
  DashboardSection,
  YOUR_TURN,
  CLOSED,
} from '../../core/gr-navigation/gr-navigation';
import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {changeIsOpen, isOwner} from '../../../utils/change-util';
import {customElement, property, observe} from '@polymer/decorators';
import {GrCursorManager} from '../../shared/gr-cursor-manager/gr-cursor-manager';
import {
  AccountInfo,
  ChangeInfo,
  ServerInfo,
  PreferencesInput,
} from '../../../types/common';
import {
  hasAttention,
  isAttentionSetEnabled,
} from '../../../utils/attention-set-util';
import {CustomKeyboardEvent} from '../../../types/events';
import {fireEvent} from '../../../utils/event-util';
import {windowLocationReload} from '../../../utils/dom-util';

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;

export interface ChangeListSection {
  name?: string;
  query?: string;
  results: ChangeInfo[];
}
export interface GrChangeList {
  $: {
    cursor: GrCursorManager;
  };
}
@customElement('gr-change-list')
export class GrChangeList extends ChangeTableMixin(
  KeyboardShortcutMixin(LegacyElementMixin(PolymerElement))
) {
  static get template() {
    return htmlTemplate;
  }

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

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

  /**
   * The logged-in user's account, or an empty object if no user is logged
   * in.
   */
  @property({type: Object})
  account: AccountInfo | undefined = undefined;

  @property({type: Array, observer: '_changesChanged'})
  changes?: ChangeInfo[];

  /**
   * ChangeInfo objects grouped into arrays. The sections and changes
   * properties should not be used together.
   */
  @property({type: Array})
  sections: ChangeListSection[] = [];

  @property({type: Array, computed: '_computeLabelNames(sections)'})
  labelNames?: string[];

  @property({type: Array})
  _dynamicHeaderEndpoints?: string[];

  @property({type: Number, notify: true})
  selectedIndex?: number;

  @property({type: Boolean})
  showNumber?: boolean; // No default value to prevent flickering.

  @property({type: Boolean})
  showStar = false;

  @property({type: Boolean})
  showReviewedState = false;

  @property({type: Object})
  keyEventTarget: HTMLElement = document.body;

  @property({type: Array})
  changeTableColumns?: string[];

  @property({type: Array})
  visibleChangeTableColumns?: string[];

  @property({type: Object})
  preferences?: PreferencesInput;

  @property({type: Object})
  _config?: ServerInfo;

  flagsService = appContext.flagsService;

  private readonly restApiService = appContext.restApiService;

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

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

  /** @override */
  ready() {
    super.ready();
    this.restApiService.getConfig().then(config => {
      this._config = config;
    });
  }

  /** @override */
  connectedCallback() {
    super.connectedCallback();
    getPluginLoader()
      .awaitPluginsLoaded()
      .then(() => {
        this._dynamicHeaderEndpoints = getPluginEndpoints().getDynamicEndpoints(
          'change-list-header'
        );
      });
  }

  /** @override */
  disconnectedCallback() {
    this.$.cursor.unsetCursor();
    super.disconnectedCallback();
  }

  /**
   * 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: KeyboardEvent) {
    if (e.keyCode === 13) {
      // Enter.
      this._openChange((e as unknown) as CustomKeyboardEvent);
    }
  }

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

  @observe('account', 'preferences', '_config')
  _computePreferences(
    account?: AccountInfo,
    preferences?: PreferencesInput,
    config?: ServerInfo
  ) {
    if (!config) {
      return;
    }

    this.changeTableColumns = this.columnNames;
    this.showNumber = false;
    this.visibleChangeTableColumns = this.getEnabledColumns(
      this.columnNames,
      config,
      this.flagsService.enabledExperiments
    );

    if (account && preferences) {
      this.showNumber = !!(
        preferences && preferences.legacycid_in_change_table
      );
      if (preferences.change_table && preferences.change_table.length > 0) {
        const prefColumns = this.renameProjectToRepoColumn(
          preferences.change_table
        );
        this.visibleChangeTableColumns = this.getEnabledColumns(
          prefColumns,
          config,
          this.flagsService.enabledExperiments
        );
      }
    }
  }

  /**
   * This methods allows us to customize the columns per section.
   *
   * @param visibleColumns are the columns according to configs and user prefs
   */
  _computeColumns(
    section?: ChangeListSection,
    visibleColumns?: string[]
  ): string[] {
    if (!section || !visibleColumns) return [];
    const cols = [...visibleColumns];
    const updatedIndex = cols.indexOf('Updated');
    if (section.name === YOUR_TURN.name && updatedIndex !== -1) {
      cols[updatedIndex] = 'Waiting';
    }
    if (section.name === CLOSED.name && updatedIndex !== -1) {
      cols[updatedIndex] = 'Submitted';
    }
    return cols;
  }

  _computeColspan(
    section?: ChangeListSection,
    visibleColumns?: string[],
    labelNames?: string[]
  ) {
    const cols = this._computeColumns(section, visibleColumns);
    if (!cols || !labelNames) return 1;
    return cols.length + labelNames.length + NUMBER_FIXED_COLUMNS;
  }

  _computeLabelNames(sections: ChangeListSection[]) {
    if (!sections) {
      return [];
    }
    let labels: string[] = [];
    const nonExistingLabel = function (item: string) {
      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: string) {
    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: ChangeInfo[]) {
    this.sections = changes ? [{results: changes}] : [];
  }

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

  _sectionHref(query: string) {
    return GerritNav.getUrlForSearchQuery(this._processQuery(query));
  }

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

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

  _computeTabIndex(sectionIndex: number, index: number, selectedIndex: number) {
    return this._computeItemSelected(sectionIndex, index, selectedIndex)
      ? 0
      : undefined;
  }

  _computeItemNeedsReview(
    account: AccountInfo | undefined,
    change: ChangeInfo,
    showReviewedState: boolean,
    config?: ServerInfo
  ) {
    return (
      !isAttentionSetEnabled(config) &&
      showReviewedState &&
      !change.reviewed &&
      !change.work_in_progress &&
      changeIsOpen(change) &&
      (!account || account._account_id !== change.owner._account_id)
    );
  }

  _computeItemHighlight(
    account?: AccountInfo,
    change?: ChangeInfo,
    config?: ServerInfo,
    sectionName?: string
  ) {
    if (!change || !account) return false;
    if (CLOSED_STATUS.indexOf(change.status) !== -1) return false;
    return isAttentionSetEnabled(config)
      ? hasAttention(config, account, change) &&
          !isOwner(change, account) &&
          sectionName === YOUR_TURN.name
      : account._account_id === change.assignee?._account_id;
  }

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

    e.preventDefault();
    this.$.cursor.next();
    this.selectedIndex = this.$.cursor.index;
  }

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

    e.preventDefault();
    this.$.cursor.previous();
    this.selectedIndex = this.$.cursor.index;
  }

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

    e.preventDefault();
    const change = this._changeForIndex(this.selectedIndex);
    if (change) GerritNav.navigateToChange(change);
  }

  _nextPage(e: CustomKeyboardEvent) {
    if (
      this.shouldSuppressKeyboardShortcut(e) ||
      (this.modifierPressed(e) &&
        !this.isModifierPressed(e, Modifier.SHIFT_KEY))
    ) {
      return;
    }

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

  _prevPage(e: CustomKeyboardEvent) {
    if (
      this.shouldSuppressKeyboardShortcut(e) ||
      (this.modifierPressed(e) &&
        !this.isModifierPressed(e, Modifier.SHIFT_KEY))
    ) {
      return;
    }

    e.preventDefault();
    this.dispatchEvent(
      new CustomEvent('previous-page', {
        composed: true,
        bubbles: true,
      })
    );
  }

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

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

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

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

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

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

  _reloadWindow() {
    windowLocationReload();
  }

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

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

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

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

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

  _getListItems() {
    const items = this.root?.querySelectorAll('gr-change-list-item');
    return !items ? [] : Array.from(items);
  }

  @observe('sections.*')
  _sectionsChanged() {
    // Flush DOM operations so that the list item elements will be loaded.
    afterNextRender(this, () => {
      this.$.cursor.stops = this._getListItems();
      this.$.cursor.moveToStart();
      if (this.selectedIndex)
        this.$.cursor.setCursorAtIndex(this.selectedIndex);
    });
  }

  _getSpecialEmptySlot(section: DashboardSection) {
    if (section.isOutgoing) return 'empty-outgoing';
    if (section.name === YOUR_TURN.name) return 'empty-your-turn';
    return '';
  }

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

declare global {
  interface HTMLElementTagNameMap {
    'gr-change-list': GrChangeList;
  }
}
