// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {LitElement, html, css} from 'lit-element';

import page from 'page';
import {connectStore, store} from 'reducers/base.js';
import * as issueV0 from 'reducers/issueV0.js';
import * as sitewide from 'reducers/sitewide.js';
import 'elements/framework/links/mr-issue-link/mr-issue-link.js';
import 'elements/framework/links/mr-crbug-link/mr-crbug-link.js';
import 'elements/framework/mr-dropdown/mr-dropdown.js';
import 'elements/framework/mr-star/mr-issue-star.js';
import {constructHref, prepareDataForDownload} from './list-to-csv-helpers.js';
import {
  issueRefToUrl,
  issueRefToString,
  issueStringToRef,
  issueToIssueRef,
  issueToIssueRefString,
  labelRefsToOneWordLabels,
} from 'shared/convertersV0.js';
import {isTextInput, findDeepEventTarget} from 'shared/dom-helpers.js';
import {
  urlWithNewParams,
  pluralize,
  setHasAny,
  objectValuesForKeys,
} from 'shared/helpers.js';
import {SHARED_STYLES} from 'shared/shared-styles.js';
import {parseColSpec, EMPTY_FIELD_VALUE} from 'shared/issue-fields.js';
import './mr-show-columns-dropdown.js';

/**
 * Column to display name mapping dictionary
 * @type {Object<string, string>}
 */
const COLUMN_DISPLAY_NAMES = Object.freeze({
  'summary': 'Summary + Labels',
});

/** @const {number} Button property value of DOM click event */
const PRIMARY_BUTTON = 0;
/** @const {number} Button property value of DOM auxclick event */
const MIDDLE_BUTTON = 1;

/** @const {string} A short transition to ease movement of list items. */
const EASE_OUT_TRANSITION = 'transform 0.05s cubic-bezier(0, 0, 0.2, 1)';

/**
 * Really high cardinality attributes like ID and Summary are unlikely to be
 * useful if grouped, so it's better to just hide the option.
 * @const {Set<string>}
 */
const UNGROUPABLE_COLUMNS = new Set(['id', 'summary']);

/**
 * Columns that should render as issue links.
 * @const {Set<string>}
 */
const ISSUE_COLUMNS = new Set(['id', 'mergedinto', 'blockedon', 'blocking']);

/**
 * `<mr-issue-list>`
 *
 * A list of issues intended to be used in multiple contexts.
 * @extends {LitElement}
 */
export class MrIssueList extends connectStore(LitElement) {
  /** @override */
  static get styles() {
    return [
      SHARED_STYLES,
      css`
        :host {
          width: 100%;
          font-size: var(--chops-main-font-size);
        }
        table {
          width: 100%;
        }
        .edit-widget-container {
          display: flex;
          flex-wrap: no-wrap;
          align-items: center;
        }
        mr-issue-star {
          --mr-star-size: 18px;
          margin-bottom: 1px;
          margin-left: 4px;
        }
        input[type="checkbox"] {
          cursor: pointer;
          margin: 0 4px;
          width: 16px;
          height: 16px;
          border-radius: 2px;
          box-sizing: border-box;
          appearance: none;
          -webkit-appearance: none;
          border: 2px solid var(--chops-gray-400);
          position: relative;
          background: var(--chops-white);
        }
        th input[type="checkbox"] {
          border-color: var(--chops-gray-500);
        }
        input[type="checkbox"]:checked {
          background: var(--chops-primary-accent-color);
          border-color: var(--chops-primary-accent-color);
        }
        input[type="checkbox"]:checked::after {
          left: 1px;
          top: 2px;
          position: absolute;
          content: "";
          width: 8px;
          height: 4px;
          border: 2px solid white;
          border-right: none;
          border-top: none;
          transform: rotate(-45deg);
        }
        td, th.group-header {
          padding: 4px 8px;
          text-overflow: ellipsis;
          border-bottom: var(--chops-normal-border);
          cursor: pointer;
          font-weight: normal;
        }
        .group-header-content {
          height: 100%;
          width: 100%;
          align-items: center;
          display: flex;
        }
        th.group-header i.material-icons {
          font-size: var(--chops-icon-font-size);
          color: var(--chops-primary-icon-color);
          margin-right: 4px;
        }
        td.ignore-navigation {
          cursor: default;
        }
        th {
          background: var(--chops-table-header-bg);
          white-space: nowrap;
          text-align: left;
          border-bottom: var(--chops-normal-border);
        }
        th.selection-header {
          padding: 3px 8px;
        }
        th > mr-dropdown, th > mr-show-columns-dropdown {
          font-weight: normal;
          color: var(--chops-link-color);
          --mr-dropdown-icon-color: var(--chops-link-color);
          --mr-dropdown-anchor-padding: 3px 8px;
          --mr-dropdown-anchor-font-weight: bold;
          --mr-dropdown-menu-min-width: 150px;
        }
        tr {
          padding: 0 8px;
        }
        tr[selected] {
          background: var(--chops-selected-bg);
        }
        td:first-child, th:first-child {
          border-left: 4px solid transparent;
        }
        tr[cursored] > td:first-child {
          border-left: 4px solid var(--chops-blue-700);
        }
        mr-crbug-link {
          /* We need the shortlink to be hidden but still accessible.
          * The opacity attribute visually hides a link while still
          * keeping it in the DOM.opacity. */
          --mr-crbug-link-opacity: 0;
          --mr-crbug-link-opacity-focused: 1;
        }
        td:hover > mr-crbug-link {
          --mr-crbug-link-opacity: 1;
        }
        .col-summary, .header-summary {
          /* Setting a table cell to 100% width makes it take up
          * all remaining space in the table, not the full width of
          * the table. */
          width: 100%;
        }
        .summary-label {
          display: inline-block;
          margin: 0 2px;
          color: var(--chops-green-800);
          text-decoration: none;
          font-size: 90%;
        }
        .summary-label:hover {
          text-decoration: underline;
        }
        td.draggable i {
          opacity: 0;
        }
        td.draggable {
          color: var(--chops-primary-icon-color);
          cursor: grab;
          padding-left: 0;
          padding-right: 0;
        }
        tr.dragged {
          opacity: 0.74;
        }
        tr:hover td.draggable i {
          opacity: 1;
        }
        .csv-download-container {
          border-bottom: none;
          text-align: end;
          cursor: default;
        }
        #hidden-data-link {
          display: none;
        }
        @media (min-width: 1024px) {
          .first-row th {
            position: sticky;
            top: var(--monorail-header-height);
            z-index: 10;
          }
        }
      `,
    ];
  }

  /** @override */
  render() {
    const selectAllChecked = this._selectedIssues.size > 0;
    const checkboxLabel = `Select ${selectAllChecked ? 'None' : 'All'}`;

    return html`
      <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
      <table cellspacing="0">
        <thead>
          <tr class="first-row">
            ${this.rerank ? html`<th></th>` : ''}
            <th class="selection-header">
              <div class="edit-widget-container">
                ${this.selectionEnabled ? html`
                  <input
                    class="select-all"
                    .checked=${selectAllChecked}
                    type="checkbox"
                    aria-label=${checkboxLabel}
                    title=${checkboxLabel}
                    @change=${this._selectAll}
                  />
                ` : ''}
              </div>
            </th>
            ${this.columns.map((column, i) => this._renderHeader(column, i))}
            <th style="z-index: ${this.highestZIndex};">
              <mr-show-columns-dropdown
                title="Show columns"
                menuAlignment="right"
                .columns=${this.columns}
                .issues=${this.issues}
                .defaultFields=${this.defaultFields}
              ></mr-show-columns-dropdown>
            </th>
          </tr>
        </thead>
        <tbody>
          ${this._renderIssues()}
        </tbody>
        ${this.userDisplayName && html`
          <tfoot><tr><td colspan=999 class="csv-download-container">
            <a id="download-link" aria-label="Download page as CSV"
                @click=${this._downloadCsv} href>CSV</a>
            <a id="hidden-data-link" download="${this.projectName}-issues.csv"
              href=${this._csvDataHref}></a>
          </td></tr></tfoot>
        `}
      </table>
    `;
  }

  /**
   * @param {string} column
   * @param {number} i The index of the column in the table.
   * @return {TemplateResult} html for header for the i-th column.
   * @private
   */
  _renderHeader(column, i) {
    // zIndex is used to render the z-index property in descending order
    const zIndex = this.highestZIndex - i;
    const colKey = column.toLowerCase();
    const name = colKey in COLUMN_DISPLAY_NAMES ? COLUMN_DISPLAY_NAMES[colKey] :
      column;
    return html`
      <th style="z-index: ${zIndex};" class="header-${colKey}">
        <mr-dropdown
          class="dropdown-${colKey}"
          .text=${name}
          .items=${this._headerActions(column, i)}
          menuAlignment="left"
        ></mr-dropdown>
      </th>`;
  }

  /**
   * @param {string} column
   * @param {number} i The index of the column in the table.
   * @return {Array<Object>} Available actions for the column.
   * @private
   */
  _headerActions(column, i) {
    const columnKey = column.toLowerCase();

    const isGroupable = this.sortingAndGroupingEnabled &&
        !UNGROUPABLE_COLUMNS.has(columnKey);

    let showOnly = [];
    if (isGroupable) {
      const values = [...this._uniqueValuesByColumn.get(columnKey)];
      if (values.length) {
        showOnly = [{
          text: 'Show only',
          items: values.map((v) => ({
            text: v,
            handler: () => this.showOnly(column, v),
          })),
        }];
      }
    }
    const sortingActions = this.sortingAndGroupingEnabled ? [
      {
        text: 'Sort up',
        handler: () => this.updateSortSpec(column),
      },
      {
        text: 'Sort down',
        handler: () => this.updateSortSpec(column, true),
      },
    ] : [];
    const actions = [
      ...sortingActions,
      ...showOnly,
      {
        text: 'Hide column',
        handler: () => this.removeColumn(i),
      },
    ];
    if (isGroupable) {
      actions.push({
        text: 'Group rows',
        handler: () => this.addGroupBy(i),
      });
    }
    return actions;
  }

  /**
   * @return {TemplateResult}
   */
  _renderIssues() {
    // Keep track of all the groups that we've seen so far to create
    // group headers as needed.
    const {issues, groupedIssues} = this;

    if (groupedIssues) {
      // Make sure issues in groups are rendered with unique indices across
      // groups to make sure hot keys and the like still work.
      let indexOffset = 0;
      return html`${groupedIssues.map(({groupName, issues}) => {
        const template = html`
          ${this._renderGroup(groupName, issues, indexOffset)}
        `;
        indexOffset += issues.length;
        return template;
      })}`;
    }

    return html`
      ${issues.map((issue, i) => this._renderRow(issue, i))}
    `;
  }

  /**
   * @param {string} groupName
   * @param {Array<Issue>} issues
   * @param {number} iOffset
   * @return {TemplateResult}
   * @private
   */
  _renderGroup(groupName, issues, iOffset) {
    if (!this.groups.length) return html``;

    const count = issues.length;
    const groupKey = groupName.toLowerCase();
    const isHidden = this._hiddenGroups.has(groupKey);

    return html`
      <tr>
        <th
          class="group-header"
          colspan="${this.numColumns}"
          @click=${() => this._toggleGroup(groupKey)}
          aria-expanded=${(!isHidden).toString()}
        >
          <div class="group-header-content">
            <i
              class="material-icons"
              title=${isHidden ? 'Show' : 'Hide'}
            >${isHidden ? 'add' : 'remove'}</i>
            ${count} ${pluralize(count, 'issue')}: ${groupName}
          </div>
        </th>
      </tr>
      ${issues.map((issue, i) => this._renderRow(issue, iOffset + i, isHidden))}
    `;
  }

  /**
   * @param {string} groupKey Lowercase group key.
   * @private
   */
  _toggleGroup(groupKey) {
    if (this._hiddenGroups.has(groupKey)) {
      this._hiddenGroups.delete(groupKey);
    } else {
      this._hiddenGroups.add(groupKey);
    }

    // Lit-element's default hasChanged check does not notice when Sets mutate.
    this.requestUpdate('_hiddenGroups');
  }

  /**
   * @param {Issue} issue
   * @param {number} i Index within the list of issues
   * @param {boolean=} isHidden
   * @return {TemplateResult}
   */
  _renderRow(issue, i, isHidden = false) {
    const rowSelected = this._selectedIssues.has(issueRefToString(issue));
    const id = issueRefToString(issue);
    const cursorId = issueRefToString(this.cursor);
    const hasCursor = cursorId === id;
    const dragged = this._dragging && rowSelected;

    return html`
      <tr
        class="row-${i} list-row ${dragged ? 'dragged' : ''}"
        ?selected=${rowSelected}
        ?cursored=${hasCursor}
        ?hidden=${isHidden}
        data-issue-ref=${id}
        data-index=${i}
        data-name=${issue.name}
        @focus=${this._setRowAsCursorOnFocus}
        @click=${this._clickIssueRow}
        @auxclick=${this._clickIssueRow}
        @keydown=${this._keydownIssueRow}
        tabindex="0"
      >
        ${this.rerank ? html`
          <td class="draggable ignore-navigation"
              @mousedown=${this._onMouseDown}>
            <i class="material-icons" title="Drag issue">drag_indicator</i>
          </td>
        ` : ''}
        <td class="ignore-navigation">
          <div class="edit-widget-container">
            ${this.selectionEnabled ? html`
              <input
                class="issue-checkbox"
                .value=${id}
                .checked=${rowSelected}
                type="checkbox"
                data-index=${i}
                aria-label="Select Issue ${issue.localId}"
                @change=${this._selectIssue}
                @click=${this._selectIssueRange}
              />
            ` : ''}
            ${this.starringEnabled ? html`
              <mr-issue-star
                .issueRef=${issueToIssueRef(issue)}
              ></mr-issue-star>
            ` : ''}
          </div>
        </td>

        ${this.columns.map((column) => html`
          <td class="col-${column.toLowerCase()}">
            ${this._renderCell(column, issue)}
          </td>
        `)}

        <td>
          <mr-crbug-link .issue=${issue}></mr-crbug-link>
        </td>
      </tr>
    `;
  }

  /**
   * @param {string} column
   * @param {Issue} issue
   * @return {TemplateResult} Html for the given column for the given issue.
   * @private
   */
  _renderCell(column, issue) {
    const columnName = column.toLowerCase();
    if (columnName === 'summary') {
      return html`
        ${issue.summary}
        ${labelRefsToOneWordLabels(issue.labelRefs).map(({label}) => html`
          <a
            class="summary-label"
            href="/p/${issue.projectName}/issues/list?q=label%3A${label}"
          >${label}</a>
        `)}
      `;
    }
    const values = this.extractFieldValues(issue, column);

    if (!values.length) return EMPTY_FIELD_VALUE;

    // TODO(zhangtiff): Make this based on the "ISSUE" field type rather than a
    // hardcoded list of issue fields.
    if (ISSUE_COLUMNS.has(columnName)) {
      return values.map((issueRefString, i) => {
        const issue = this._issueForRefString(issueRefString, this.projectName);
        return html`
          <mr-issue-link
            .projectName=${this.projectName}
            .issue=${issue}
            .queryParams=${this._queryParams}
            short
          ></mr-issue-link>${values.length - 1 > i ? ', ' : ''}
        `;
      });
    }
    return values.join(', ');
  }

  /** @override */
  static get properties() {
    return {
      /**
       * Array of columns to display.
       */
      columns: {type: Array},
      /**
       * Array of built in fields that are available outside of project
       * configuration.
       */
      defaultFields: {type: Array},
      /**
       * A function that takes in an issue and a field name and returns the
       * value for that field in the issue. This function accepts custom fields,
       * built in fields, and ad hoc fields computed from label prefixes.
       */
      extractFieldValues: {type: Object},
      /**
       * Array of columns that are used as groups for issues.
       */
      groups: {type: Array},
      /**
       * List of issues to display.
       */
      issues: {type: Array},
      /**
       * A Redux action creator that calls the API to rerank the issues
       * in the list. If set, reranking is enabled for this issue list.
       */
      rerank: {type: Object},
      /**
       * Whether issues should be selectable or not.
       */
      selectionEnabled: {type: Boolean},
      /**
       * Whether issues should be sortable and groupable or not. This will
       * change how column headers will be displayed. The ability to sort and
       * group are currently coupled.
       */
      sortingAndGroupingEnabled: {type: Boolean},
      /**
       * Whether to show issue starring or not.
       */
      starringEnabled: {type: Boolean},
      /**
       * A query representing the current set of matching issues in the issue
       * list. Does not necessarily match queryParams.q since queryParams.q can
       * be empty while currentQuery is set to a default project query.
       */
      currentQuery: {type: String},
      /**
       * Object containing URL parameters to be preserved when issue links are
       * clicked. This Object is only used for the purpose of preserving query
       * parameters across links, not for the purpose of evaluating the query
       * parameters themselves to get values like columns, sort, or q. This
       * separation is important because we don't want to tightly couple this
       * list component with a specific URL system.
       * @private
       */
      _queryParams: {type: Object},
      /**
       * The initial cursor that a list view uses. This attribute allows users
       * of the list component to specify and control the cursor. When the
       * initialCursor attribute updates, the list focuses the element specified
       * by the cursor.
       */
      initialCursor: {type: String},
      /**
       * Logged in user's display name
       */
      userDisplayName: {type: String},
      /**
       * IssueRef Object specifying which issue the user is currently focusing.
       */
      _localCursor: {type: Object},
      /**
       * Set of group keys that are currently hidden.
       */
      _hiddenGroups: {type: Object},
      /**
       * Set of all selected issues where each entry is an issue ref string.
       */
      _selectedIssues: {type: Object},
      /**
       * List of unique phase names for all phases in issues.
       */
      _phaseNames: {type: Array},
      /**
       * True iff the user is dragging issues.
       */
      _dragging: {type: Boolean},
      /**
       * CSV data in data HREF format, used to download csv
       */
      _csvDataHref: {type: String},
      /**
       * Function to get a full Issue object for a given ref string.
       */
      _issueForRefString: {type: Object},
    };
  };

  /** @override */
  constructor() {
    super();
    /** @type {Array<Issue>} */
    this.issues = [];
    // TODO(jojwang): monorail:6336#c8, when ezt listissues page is fully
    // deprecated, remove phaseNames from mr-issue-list.
    this._phaseNames = [];
    /** @type {IssueRef} */
    this._localCursor;
    /** @type {IssueRefString} */
    this.initialCursor;
    /** @type {Set<IssueRefString>} */
    this._selectedIssues = new Set();
    /** @type {string} */
    this.projectName;
    /** @type {Object} */
    this._queryParams = {};
    /** @type {string} */
    this.currentQuery = '';
    /**
     * @param {Array<String>} items
     * @param {number} index
     * @return {Promise<void>}
     */
    this.rerank = null;
    /** @type {boolean} */
    this.selectionEnabled = false;
    /** @type {boolean} */
    this.sortingAndGroupingEnabled = false;
    /** @type {boolean} */
    this.starringEnabled = false;
    /** @type {Array} */
    this.columns = ['ID', 'Summary'];
    /** @type {Array<string>} */
    this.defaultFields = [];
    /** @type {Array} */
    this.groups = [];
    this.userDisplayName = '';

    /** @type {function(KeyboardEvent): void} */
    this._boundRunListHotKeys = this._runListHotKeys.bind(this);
    /** @type {function(MouseEvent): void} */
    this._boundOnMouseMove = this._onMouseMove.bind(this);
    /** @type {function(MouseEvent): void} */
    this._boundOnMouseUp = this._onMouseUp.bind(this);

    /**
     * @param {Issue} _issue
     * @param {string} _fieldName
     * @return {Array<string>}
     */
    this.extractFieldValues = (_issue, _fieldName) => [];

    /**
     * @param {IssueRefString} _issueRefString
     * @param {string} projectName The currently viewed project.
     * @return {Issue}
     */
    this._issueForRefString = (_issueRefString, projectName) =>
      issueStringToRef(_issueRefString, projectName);

    this._hiddenGroups = new Set();

    this._starredIssues = new Set();
    this._fetchingStarredIssues = false;
    this._starringIssues = new Map();

    this._uniqueValuesByColumn = new Map();

    this._dragging = false;
    this._mouseX = null;
    this._mouseY = null;

    /** @type {number} */
    this._lastSelectedCheckbox = -1;

    // Expose page.js for stubbing.
    this._page = page;
    /** @type {string} page data in csv format as data href */
    this._csvDataHref = '';
  };

  /** @override */
  stateChanged(state) {
    this._starredIssues = issueV0.starredIssues(state);
    this._fetchingStarredIssues =
        issueV0.requests(state).fetchStarredIssues.requesting;
    this._starringIssues = issueV0.starringIssues(state);

    this._phaseNames = (issueV0.issueListPhaseNames(state) || []);
    this._queryParams = sitewide.queryParams(state);

    this._issueForRefString = issueV0.issueForRefString(state);
  }

  /** @override */
  firstUpdated() {
    // Only attach an event listener once the DOM has rendered.
    window.addEventListener('keydown', this._boundRunListHotKeys);
    this._dataLink = this.shadowRoot.querySelector('#hidden-data-link');
  }

  /** @override */
  disconnectedCallback() {
    super.disconnectedCallback();

    window.removeEventListener('keydown', this._boundRunListHotKeys);
  }

  /**
   * @override
   * @fires CustomEvent#selectionChange
   */
  update(changedProperties) {
    if (changedProperties.has('issues')) {
      // Clear selected issues to avoid an ever-growing Set size. In the future,
      // we may want to consider saving selections across issue reloads, though,
      // such as in the case or list refreshing.
      this._selectedIssues = new Set();
      this.dispatchEvent(new CustomEvent('selectionChange'));

      // Clear group toggle state when the list of issues changes to prevent an
      // ever-growing Set size.
      this._hiddenGroups = new Set();

      this._lastSelectedCheckbox = -1;
    }

    const valuesByColumnArgs = ['issues', 'columns', 'extractFieldValues'];
    if (setHasAny(changedProperties, valuesByColumnArgs)) {
      this._uniqueValuesByColumn = this._computeUniqueValuesByColumn(
          ...objectValuesForKeys(this, valuesByColumnArgs));
    }

    super.update(changedProperties);
  }

  /** @override */
  updated(changedProperties) {
    if (changedProperties.has('initialCursor')) {
      const ref = issueStringToRef(this.initialCursor, this.projectName);
      const row = this._getRowFromIssueRef(ref);
      if (row) {
        row.focus();
      }
    }
  }

  /**
   * Iterates through all issues in a list to sort unique values
   * across columns, for use in the "Show only" feature.
   * @param {Array} issues
   * @param {Array} columns
   * @param {function(Issue, string): Array<string>} fieldExtractor
   * @return {Map} Map where each entry has a String key for the
   *   lowercase column name and a Set value, continuing all values for
   *   that column.
   */
  _computeUniqueValuesByColumn(issues, columns, fieldExtractor) {
    const valueMap = new Map(
        columns.map((col) => [col.toLowerCase(), new Set()]));

    issues.forEach((issue) => {
      columns.forEach((col) => {
        const key = col.toLowerCase();
        const valueSet = valueMap.get(key);

        const values = fieldExtractor(issue, col);
        // Note: This allows multiple casings of the same values to be added
        // to the Set.
        values.forEach((v) => valueSet.add(v));
      });
    });
    return valueMap;
  }

  /**
   * Used for dynamically computing z-index to ensure column dropdowns overlap
   * properly.
   */
  get highestZIndex() {
    return this.columns.length + 10;
  }

  /**
   * The number of columns displayed in the table. This is the count of
   * customized columns + number of built in columns.
   */
  get numColumns() {
    return this.columns.length + 2;
  }

  /**
   * Sort issues into groups if groups are defined. The grouping feature is used
   * when the "groupby" URL parameter is set in the list view.
   */
  get groupedIssues() {
    if (!this.groups || !this.groups.length) return;

    const issuesByGroup = new Map();

    this.issues.forEach((issue) => {
      const groupName = this._groupNameForIssue(issue);
      const groupKey = groupName.toLowerCase();

      if (!issuesByGroup.has(groupKey)) {
        issuesByGroup.set(groupKey, {groupName, issues: [issue]});
      } else {
        const entry = issuesByGroup.get(groupKey);
        entry.issues.push(issue);
      }
    });
    return [...issuesByGroup.values()];
  }

  /**
   * The currently selected issue, with _localCursor overriding initialCursor.
   *
   * @return {IssueRef} The currently selected issue.
   */
  get cursor() {
    if (this._localCursor) {
      return this._localCursor;
    }
    if (this.initialCursor) {
      return issueStringToRef(this.initialCursor, this.projectName);
    }
    return {};
  }

  /**
   * Computes the name of the group that an issue belongs to. Issues are grouped
   * by fields that the user specifies and group names are generated using a
   * combination of an issue's field values for all specified groups.
   *
   * @param {Issue} issue
   * @return {string}
   */
  _groupNameForIssue(issue) {
    const groups = this.groups;
    const keyPieces = [];

    groups.forEach((group) => {
      const values = this.extractFieldValues(issue, group);
      if (!values.length) {
        keyPieces.push(`-has:${group}`);
      } else {
        values.forEach((v) => {
          keyPieces.push(`${group}=${v}`);
        });
      }
    });

    return keyPieces.join(' ');
  }

  /**
   * @return {Array<Issue>} Selected issues in the order they appear.
   */
  get selectedIssues() {
    return this.issues.filter((issue) =>
      this._selectedIssues.has(issueToIssueRefString(issue)));
  }

  /**
   * Update the search query to filter values matching a specific one.
   *
   * @param {string} column name of the column being filtered.
   * @param {string} value value of the field to filter by.
   */
  showOnly(column, value) {
    column = column.toLowerCase();

    // TODO(zhangtiff): Handle edge cases where column names are not
    // mapped directly to field names. For example, "AllLabels", should
    // query for "Labels".
    const querySegment = `${column}=${value}`;

    let query = this.currentQuery.trim();

    if (!query.includes(querySegment)) {
      query += ' ' + querySegment;

      this._updateQueryParams({q: query.trim()}, ['start']);
    }
  }

  /**
   * Update sort parameter in the URL based on user input.
   *
   * @param {string} column name of the column to be sorted.
   * @param {boolean} descending descending or ascending order.
   */
  updateSortSpec(column, descending = false) {
    column = column.toLowerCase();
    const oldSpec = this._queryParams.sort || '';
    const columns = parseColSpec(oldSpec.toLowerCase());

    // Remove any old instances of the same sort spec.
    const newSpec = columns.filter(
        (c) => c && c !== column && c !== `-${column}`);

    newSpec.unshift(`${descending ? '-' : ''}${column}`);

    this._updateQueryParams({sort: newSpec.join(' ')}, ['start']);
  }

  /**
   * Updates the groupby URL parameter to include a new column to group.
   *
   * @param {number} i index of the column to be grouped.
   */
  addGroupBy(i) {
    const groups = [...this.groups];
    const columns = [...this.columns];
    const groupedColumn = columns[i];
    columns.splice(i, 1);

    groups.unshift(groupedColumn);

    this._updateQueryParams({
      groupby: groups.join(' '),
      colspec: columns.join('+'),
    }, ['start']);
  }

  /**
   * Removes the column at a particular index.
   *
   * @param {number} i the issue column to be removed.
   */
  removeColumn(i) {
    const columns = [...this.columns];
    columns.splice(i, 1);
    this.reloadColspec(columns);
  }

  /**
   * Adds a new column to a particular index.
   *
   * @param {string} name of the new column added.
   */
  addColumn(name) {
    this.reloadColspec([...this.columns, name]);
  }

  /**
   * Reflects changes to the columns of an issue list to the URL, through
   * frontend routing.
   *
   * @param {Array} newColumns the new colspec to set in the URL.
   */
  reloadColspec(newColumns) {
    this._updateQueryParams({colspec: newColumns.join('+')});
  }

  /**
   * Navigates to the same URL as the current page, but with query
   * params updated.
   *
   * @param {Object} newParams keys and values of the queryParams
   * Object to be updated.
   * @param {Array} deletedParams keys to be cleared from queryParams.
   */
  _updateQueryParams(newParams = {}, deletedParams = []) {
    const url = urlWithNewParams(this._baseUrl(), this._queryParams, newParams,
        deletedParams);
    this._page(url);
  }

  /**
   * Get the current URL of the page, without query params. Useful for
   * test stubbing.
   *
   * @return {string} the URL of the list page, without params.
   */
  _baseUrl() {
    return window.location.pathname;
  }

  /**
   * Run issue list hot keys. This event handler needs to be bound globally
   * because a list cursor can be defined even when no element in the list is
   * focused.
   * @param {KeyboardEvent} e
   */
  _runListHotKeys(e) {
    if (!this.issues || !this.issues.length) return;
    const target = findDeepEventTarget(e);
    if (!target || isTextInput(target)) return;

    const key = e.key;

    const activeRow = this._getCursorElement();

    let i = -1;
    if (activeRow) {
      i = Number.parseInt(activeRow.dataset.index);

      const issue = this.issues[i];

      switch (key) {
        case 's': // Star focused issue.
          this._starIssue(issueToIssueRef(issue));
          return;
        case 'x': // Toggle selection of focused issue.
          const issueRefString = issueToIssueRefString(issue);
          this._updateSelectedIssues([issueRefString],
              !this._selectedIssues.has(issueRefString));
          return;
        case 'o': // Open current issue.
        case 'O': // Open current issue in new tab.
          this._navigateToIssue(issue, e.shiftKey);
          return;
      }
    }

    // Move up and down the issue list.
    // 'j' moves 'down'.
    // 'k' moves 'up'.
    if (key === 'j' || key === 'k') {
      if (key === 'j') { // Navigate down the list.
        i += 1;
        if (i >= this.issues.length) {
          i = 0;
        }
      } else if (key === 'k') { // Navigate up the list.
        i -= 1;
        if (i < 0) {
          i = this.issues.length - 1;
        }
      }

      const nextRow = this.shadowRoot.querySelector(`.row-${i}`);
      this._setRowAsCursor(nextRow);
    }
  }

  /**
   * @return {HTMLTableRowElement}
   */
  _getCursorElement() {
    const cursor = this.cursor;
    if (cursor) {
      // If there's a cursor set, use that instead of focus.
      return this._getRowFromIssueRef(cursor);
    }
    return;
  }

  /**
   * @param {FocusEvent} e
   */
  _setRowAsCursorOnFocus(e) {
    this._setRowAsCursor(/** @type {HTMLTableRowElement} */ (e.target));
  }

  /**
   *
   * @param {HTMLTableRowElement} row
   */
  _setRowAsCursor(row) {
    this._localCursor = issueStringToRef(row.dataset.issueRef,
        this.projectName);
    row.focus();
  }

  /**
   * @param {IssueRef} ref The issueRef to query for.
   * @return {HTMLTableRowElement}
   */
  _getRowFromIssueRef(ref) {
    return this.shadowRoot.querySelector(
        `.list-row[data-issue-ref="${issueRefToString(ref)}"]`);
  }

  /**
   * Returns an Array containing every <tr> in the list, excluding the header.
   * @return {Array<HTMLTableRowElement>}
   */
  _getRows() {
    return Array.from(this.shadowRoot.querySelectorAll('.list-row'));
  }

  /**
   * Returns an Array containing every selected <tr> in the list.
   * @return {Array<HTMLTableRowElement>}
   */
  _getSelectedRows() {
    return this._getRows().filter((row) => {
      return this._selectedIssues.has(row.dataset.issueRef);
    });
  }

  /**
   * @param {IssueRef} issueRef Issue to star
   */
  _starIssue(issueRef) {
    if (!this.starringEnabled) return;
    const issueKey = issueRefToString(issueRef);

    // TODO(zhangtiff): Find way to share star disabling logic more.
    const isStarring = this._starringIssues.has(issueKey) &&
      this._starringIssues.get(issueKey).requesting;
    const starEnabled = !this._fetchingStarredIssues && !isStarring;
    if (starEnabled) {
      const newIsStarred = !this._starredIssues.has(issueKey);
      this._starIssueInternal(issueRef, newIsStarred);
    }
  }

  /**
   * Wrap store.dispatch and issue.star, for testing.
   *
   * @param {IssueRef} issueRef the issue being starred.
   * @param {boolean} newIsStarred whether to star or unstar the issue.
   * @private
   */
  _starIssueInternal(issueRef, newIsStarred) {
    store.dispatch(issueV0.star(issueRef, newIsStarred));
  }
  /**
   * @param {Event} e
   * @fires CustomEvent#open-dialog
   * @private
   */
  _selectAll(e) {
    const checkbox = /** @type {HTMLInputElement} */ (e.target);

    if (checkbox.checked) {
      this._selectedIssues = new Set(this.issues.map(issueRefToString));
    } else {
      this._selectedIssues = new Set();
    }
    this.dispatchEvent(new CustomEvent('selectionChange'));
  }

  // TODO(zhangtiff): Implement Shift+Click to select a range of checkboxes
  // for the 'x' hot key.
  /**
   * @param {MouseEvent} e
   * @private
   */
  _selectIssueRange(e) {
    if (!this.selectionEnabled) return;

    const checkbox = /** @type {HTMLInputElement} */ (e.target);

    const index = Number.parseInt(checkbox.dataset.index);
    if (Number.isNaN(index)) {
      console.error('Issue checkbox has invalid data-index attribute.');
      return;
    }

    const lastIndex = this._lastSelectedCheckbox;
    if (e.shiftKey && lastIndex >= 0) {
      const newCheckedState = checkbox.checked;

      const start = Math.min(lastIndex, index);
      const end = Math.max(lastIndex, index) + 1;

      const updatedIssueKeys = this.issues.slice(start, end).map(
          issueToIssueRefString);
      this._updateSelectedIssues(updatedIssueKeys, newCheckedState);
    }

    this._lastSelectedCheckbox = index;
  }

  /**
   * @param {Event} e
   * @private
   */
  _selectIssue(e) {
    if (!this.selectionEnabled) return;

    const checkbox = /** @type {HTMLInputElement} */ (e.target);
    const issueKey = checkbox.value;

    this._updateSelectedIssues([issueKey], checkbox.checked);
  }

  /**
   * @param {Array<IssueRefString>} issueKeys Stringified issue refs.
   * @param {boolean} selected
   * @fires CustomEvent#selectionChange
   * @private
   */
  _updateSelectedIssues(issueKeys, selected) {
    let hasChanges = false;

    issueKeys.forEach((issueKey) => {
      const oldSelection = this._selectedIssues.has(issueKey);

      if (selected) {
        this._selectedIssues.add(issueKey);
      } else if (this._selectedIssues.has(issueKey)) {
        this._selectedIssues.delete(issueKey);
      }

      const newSelection = this._selectedIssues.has(issueKey);

      hasChanges = hasChanges || newSelection !== oldSelection;
    });


    if (hasChanges) {
      this.requestUpdate('_selectedIssues');
      this.dispatchEvent(new CustomEvent('selectionChange'));
    }
  }

  /**
   * Handles 'Enter' being pressed when a row is focused.
   * Note we install the 'Enter' listener on the row rather than the window so
   * 'Enter' behaves as expected when the focus is on other elements.
   *
   * @param {KeyboardEvent} e
   * @private
   */
  _keydownIssueRow(e) {
    if (e.key === 'Enter') {
      this._maybeOpenIssueRow(e);
    }
  }

  /**
   * Handles mouseDown to start drag events.
   * @param {MouseEvent} event
   * @private
   */
  _onMouseDown(event) {
    event.cancelable && event.preventDefault();

    this._mouseX = event.clientX;
    this._mouseY = event.clientY;

    this._setRowAsCursor(event.currentTarget.parentNode);
    this._startDrag();

    // We add the event listeners to window because the mouse can go out of the
    // bounds of the target element. window.mouseUp still triggers even if the
    // mouse is outside the browser window.
    window.addEventListener('mousemove', this._boundOnMouseMove);
    window.addEventListener('mouseup', this._boundOnMouseUp);
  }

  /**
   * Handles mouseMove to continue drag events.
   * @param {MouseEvent} event
   * @private
   */
  _onMouseMove(event) {
    event.cancelable && event.preventDefault();

    const x = event.clientX - this._mouseX;
    const y = event.clientY - this._mouseY;
    this._continueDrag(x, y);
  }

  /**
   * Handles mouseUp to end drag events.
   * @param {MouseEvent} event
   * @private
   */
  _onMouseUp(event) {
    event.cancelable && event.preventDefault();

    window.removeEventListener('mousemove', this._boundOnMouseMove);
    window.removeEventListener('mouseup', this._boundOnMouseUp);

    this._endDrag(event.clientY - this._mouseY);
  }

  /**
   * Gives a visual indicator that we've started dragging an issue row.
   * @private
   */
  _startDrag() {
    this._dragging = true;

    // If the dragged row is not selected, select it.
    // TODO(dtu): Allow dragging an existing selection for multi-drag.
    const issueRefString = issueRefToString(this.cursor);
    this._selectedIssues = new Set();
    this._updateSelectedIssues([issueRefString], true);
  }

  /**
   * @param {number} x The x-distance the cursor has moved since mouseDown.
   * @param {number} y The y-distance the cursor has moved since mouseDown.
   * @private
   */
  _continueDrag(x, y) {
    // Unselected rows: Transition them to their new positions.
    const [rows, initialIndex, finalIndex] = this._computeRerank(y);
    this._translateRows(rows, initialIndex, finalIndex);

    // Selected rows: Stick them to the cursor. No transition.
    for (const row of this._getSelectedRows()) {
      row.style.transform = `translate(${x}px, ${y}px`;
    };
  }

  /**
   * @param {number} y The y-distance the cursor has moved since mouseDown.
   * @private
   */
  async _endDrag(y) {
    this._dragging = false;

    // Unselected rows: Transition them to their new positions.
    const [rows, initialIndex, finalIndex] = this._computeRerank(y);
    const targetTranslation =
        this._translateRows(rows, initialIndex, finalIndex);

    // Selected rows: Transition them to their final positions
    // and reset their opacity.
    const selectedRows = this._getSelectedRows();
    for (const row of selectedRows) {
      row.style.transition = EASE_OUT_TRANSITION;
      row.style.transform = `translate(0px, ${targetTranslation}px)`;
    };

    // Submit the change.
    const items = selectedRows.map((row) => row.dataset.name);
    await this.rerank(items, finalIndex);

    // Reset the transforms.
    for (const row of this._getRows()) {
      row.style.transition = '';
      row.style.transform = '';
    };

    // Set the cursor to the new row.
    // In order to focus the correct element, we need the DOM to be in sync
    // with the issue list. We modified this.issues, so wait for a re-render.
    await this.updateComplete;
    const selector = `.list-row[data-index="${finalIndex}"]`;
    this.shadowRoot.querySelector(selector).focus();
  }

  /**
   * Computes the starting and ending indices of the cursor row,
   * given how far the mouse has been dragged in the y-direction.
   * The indices assume the cursor row has been removed from the list.
   * @param {number} y The y-distance the cursor has moved since mouseDown.
   * @return {[Array<HTMLTableRowElement>, number, number]} A tuple containing:
   *     An Array of table rows with the cursor row removed.
   *     The initial index of the cursor row.
   *     The final index of the cursor row.
   * @private
   */
  _computeRerank(y) {
    const row = this._getCursorElement();
    const rows = this._getRows();
    const listTop = row.parentNode.offsetTop;

    // Find the initial index of the cursor row.
    // TODO(dtu): If we support multi-drag, this should be the adjusted index of
    // the first selected row after collapsing spaces in the selected group.
    const initialIndex = rows.indexOf(row);
    rows.splice(initialIndex, 1);

    // Compute the initial and final y-positions of the top
    // of the cursor row relative to the top of the list.
    const initialY = row.offsetTop - listTop;
    const finalY = initialY + y;

    // Compute the final index of the cursor row.
    // The break points are the halfway marks of each row.
    let finalIndex = 0;
    for (finalIndex = 0; finalIndex < rows.length; ++finalIndex) {
      const rowTop = rows[finalIndex].offsetTop - listTop -
          (finalIndex >= initialIndex ? row.scrollHeight : 0);
      const breakpoint = rowTop + rows[finalIndex].scrollHeight / 2;
      if (breakpoint > finalY) {
        break;
      }
    }

    return [rows, initialIndex, finalIndex];
  }

  /**
   * @param {Array<HTMLTableRowElement>} rows Array of table rows with the
   *    cursor row removed.
   * @param {number} initialIndex The initial index of the cursor row.
   * @param {number} finalIndex The final index of the cursor row.
   * @return {number} The number of pixels the cursor row moved.
   * @private
   */
  _translateRows(rows, initialIndex, finalIndex) {
    const firstIndex = Math.min(initialIndex, finalIndex);
    const lastIndex = Math.max(initialIndex, finalIndex);

    const rowHeight = this._getCursorElement().scrollHeight;
    const translation = initialIndex < finalIndex ? -rowHeight : rowHeight;

    let targetTranslation = 0;
    for (let i = 0; i < rows.length; ++i) {
      rows[i].style.transition = EASE_OUT_TRANSITION;
      if (i >= firstIndex && i < lastIndex) {
        rows[i].style.transform = `translate(0px, ${translation}px)`;
        targetTranslation += rows[i].scrollHeight;
      } else {
        rows[i].style.transform = '';
      }
    }

    return initialIndex < finalIndex ? targetTranslation : -targetTranslation;
  }

  /**
   * Handle click and auxclick on issue row.
   * @param {MouseEvent} event
   * @private
   */
  _clickIssueRow(event) {
    if (event.button === PRIMARY_BUTTON || event.button === MIDDLE_BUTTON) {
      this._maybeOpenIssueRow(
          event, /* openNewTab= */ event.button === MIDDLE_BUTTON);
    }
  }

  /**
   * Checks that the given event should not be ignored, then navigates to the
   * issue associated with the row.
   *
   * @param {MouseEvent|KeyboardEvent} rowEvent A click or 'enter' on a row.
   * @param {boolean=} openNewTab Forces opening in a new tab
   * @private
   */
  _maybeOpenIssueRow(rowEvent, openNewTab = false) {
    const path = rowEvent.composedPath();
    const containsIgnoredElement = path.find(
        (node) => (node.tagName || '').toUpperCase() === 'A' ||
        (node.classList && node.classList.contains('ignore-navigation')));
    if (containsIgnoredElement) return;

    const row = /** @type {HTMLTableRowElement} */ (rowEvent.currentTarget);

    const i = Number.parseInt(row.dataset.index);

    if (i >= 0 && i < this.issues.length) {
      this._navigateToIssue(this.issues[i], openNewTab || rowEvent.metaKey ||
          rowEvent.ctrlKey);
    }
  }

  /**
   * @param {Issue} issue
   * @param {boolean} newTab
   * @private
   */
  _navigateToIssue(issue, newTab) {
    const link = issueRefToUrl(issueToIssueRef(issue),
        this._queryParams);

    if (newTab) {
      // Whether the link opens in a new tab or window is based on the
      // user's browser preferences.
      window.open(link, '_blank', 'noopener');
    } else {
      this._page(link);
    }
  }

  /**
   * Convert an issue's data into an array of strings, where the columns
   * match this.columns. Extracting data like _renderCell.
   * @param {Issue} issue
   * @return {Array<string>}
   * @private
   */
  _convertIssueToPlaintextArray(issue) {
    return this.columns.map((column) => {
      return this.extractFieldValues(issue, column).join(', ');
    });
  }

  /**
   * Convert each Issue into array of strings, where the columns
   * match this.columns.
   * @return {Array<Array<string>>}
   * @private
   */
  _convertIssuesToPlaintextArrays() {
    return this.issues.map(this._convertIssueToPlaintextArray.bind(this));
  }

  /**
   * Download content as csv. Conversion to CSV only on button click
   * instead of on data change because CSV download is not often used.
   * @param {MouseEvent} event
   * @private
   */
  async _downloadCsv(event) {
    event.preventDefault();

    if (this.userDisplayName) {
      // convert issues to array of arrays of strings
      const issueData = this._convertIssuesToPlaintextArrays();

      // convert the data into csv formatted string.
      const csvDataString = prepareDataForDownload(issueData, this.columns);

      // construct data href
      const href = constructHref(csvDataString);

      // modify a tag's href
      this._csvDataHref = href;
      await this.requestUpdate('_csvDataHref');

      // click to trigger download
      this._dataLink.click();

      // reset dataHref
      this._csvDataHref = '';
    }
  }
};

customElements.define('mr-issue-list', MrIssueList);
