// Copyright 2019 The Chromium Authors
// 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 qs from 'qs';
import {store, connectStore} from 'reducers/base.js';
import * as issueV0 from 'reducers/issueV0.js';
import * as projectV0 from 'reducers/projectV0.js';
import * as userV0 from 'reducers/userV0.js';
import * as sitewide from 'reducers/sitewide.js';
import * as ui from 'reducers/ui.js';
import {prpcClient} from 'prpc-client-instance.js';
import {SERVER_LIST_ISSUES_LIMIT} from 'shared/consts/index.js';
import {DEFAULT_ISSUE_FIELD_LIST, parseColSpec} from 'shared/issue-fields.js';
import {
  shouldWaitForDefaultQuery,
  urlWithNewParams,
  userIsMember,
} from 'shared/helpers.js';
import {SHARED_STYLES} from 'shared/shared-styles.js';
import 'elements/framework/dialogs/mr-change-columns/mr-change-columns.js';
// eslint-disable-next-line max-len
import 'elements/framework/dialogs/mr-issue-hotlists-action/mr-update-issue-hotlists-dialog.js';
import 'elements/framework/mr-button-bar/mr-button-bar.js';
import 'elements/framework/mr-dropdown/mr-dropdown.js';
import 'elements/framework/mr-issue-list/mr-issue-list.js';
import '../mr-mode-selector/mr-mode-selector.js';

export const DEFAULT_ISSUES_PER_PAGE = 100;
const PARAMS_THAT_TRIGGER_REFRESH = ['sort', 'groupby', 'num',
  'start'];
const SNACKBAR_LOADING = 'Loading issues...';

/**
 * `<mr-list-page>`
 *
 * Container page for the list view
 */
export class MrListPage extends connectStore(LitElement) {
  /** @override */
  static get styles() {
    return [
      SHARED_STYLES,
      css`
        :host {
          display: block;
          box-sizing: border-box;
          width: 100%;
          padding: 0.5em 8px;
        }
        .container-loading,
        .container-no-issues {
          width: 100%;
          box-sizing: border-box;
          padding: 0 8px;
          font-size: var(--chops-main-font-size);
        }
        .container-no-issues {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
        }
        .container-no-issues p {
          margin: 0.5em;
        }
        .no-issues-block {
          display: block;
          padding: 1em 16px;
          margin-top: 1em;
          flex-grow: 1;
          width: 300px;
          max-width: 100%;
          text-align: center;
          background: var(--chops-primary-accent-bg);
          border-radius: 8px;
          border-bottom: var(--chops-normal-border);
        }
        .no-issues-block[hidden] {
          display: none;
        }
        .list-controls {
          display: flex;
          align-items: center;
          justify-content: space-between;
          width: 100%;
          padding: 0.5em 0;
        }
        .right-controls {
          flex-grow: 0;
          display: flex;
          align-items: center;
          justify-content: flex-end;
        }
        .next-link, .prev-link {
          display: inline-block;
          margin: 0 8px;
        }
        mr-mode-selector {
          margin-left: 8px;
        }
      `,
    ];
  }

  /** @override */
  render() {
    const selectedRefs = this.selectedIssues.map(
        ({localId, projectName}) => ({localId, projectName}));

    return html`
      ${this._renderControls()}
      ${this._renderListBody()}
      <mr-update-issue-hotlists-dialog
        .issueRefs=${selectedRefs}
        @saveSuccess=${this._showHotlistSaveSnackbar}
      ></mr-update-issue-hotlists-dialog>
      <mr-change-columns
        .columns=${this.columns}
        .queryParams=${this._queryParams}
      ></mr-change-columns>
    `;
  }

  /**
   * @return {TemplateResult}
   */
  _renderListBody() {
    if (!this._issueListLoaded) {
      return html`
        <div class="container-loading">
          Loading...
        </div>
      `;
    } else if (!this.totalIssues) {
      return html`
        <div class="container-no-issues">
          <p>
            The search query:
          </p>
          <strong>${this._queryParams.q}</strong>
          <p>
            did not generate any results.
          </p>
          <div class="no-issues-block">
            Type a new query in the search box above
          </div>
          <a
            href=${this._urlWithNewParams({can: 2, q: ''})}
            class="no-issues-block view-all-open"
          >
            View all open issues
          </a>
          <a
            href=${this._urlWithNewParams({can: 1})}
            class="no-issues-block consider-closed"
            ?hidden=${this._queryParams.can === '1'}
          >
            Consider closed issues
          </a>
        </div>
      `;
    }

    return html`
      <mr-issue-list
        .issues=${this.issues}
        .projectName=${this.projectName}
        .queryParams=${this._queryParams}
        .initialCursor=${this._queryParams.cursor}
        .currentQuery=${this.currentQuery}
        .currentCan=${this.currentCan}
        .columns=${this.columns}
        .defaultFields=${DEFAULT_ISSUE_FIELD_LIST}
        .extractFieldValues=${this._extractFieldValues}
        .groups=${this.groups}
        .userDisplayName=${this.userDisplayName}
        ?selectionEnabled=${this.editingEnabled}
        ?sortingAndGroupingEnabled=${true}
        ?starringEnabled=${this.starringEnabled}
        @selectionChange=${this._setSelectedIssues}
      ></mr-issue-list>
    `;
  }

  /**
   * @return {TemplateResult}
   */
  _renderControls() {
    const maxItems = this.maxItems;
    const startIndex = this.startIndex;
    const end = Math.min(startIndex + maxItems, this.totalIssues);
    const hasNext = end < this.totalIssues;
    const hasPrev = startIndex > 0;

    return html`
      <div class="list-controls">
        <div>
          ${this.editingEnabled ? html`
            <mr-button-bar .items=${this._actions}></mr-button-bar>
          ` : ''}
        </div>

        <div class="right-controls">
          ${hasPrev ? html`
            <a
              href=${this._urlWithNewParams({start: startIndex - maxItems})}
              class="prev-link"
            >
              &lsaquo; Prev
            </a>
          ` : ''}
          <div class="issue-count" ?hidden=${!this.totalIssues}>
            ${startIndex + 1} - ${end} of ${this.totalIssuesDisplay}
          </div>
          ${hasNext ? html`
            <a
              href=${this._urlWithNewParams({start: startIndex + maxItems})}
              class="next-link"
            >
              Next &rsaquo;
            </a>
          ` : ''}
          <mr-mode-selector
            .projectName=${this.projectName}
            .queryParams=${this._queryParams}
            value="list"
          ></mr-mode-selector>
        </div>
      </div>
    `;
  }

  /** @override */
  static get properties() {
    return {
      issues: {type: Array},
      totalIssues: {type: Number},
      /** @private {Object} */
      _queryParams: {type: Object},
      projectName: {type: String},
      _fetchingIssueList: {type: Boolean},
      _issueListLoaded: {type: Boolean},
      selectedIssues: {type: Array},
      columns: {type: Array},
      userDisplayName: {type: String},
      /**
       * The current search string the user is querying for.
       */
      currentQuery: {type: String},
      /**
       * The current canned query the user is searching for.
       */
      currentCan: {type: String},
      /**
       * 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},
      _isLoggedIn: {type: Boolean},
      _currentUser: {type: Object},
      _usersProjects: {type: Object},
      _fetchIssueListError: {type: String},
      _presentationConfigLoaded: {type: Boolean},
    };
  };

  /** @override */
  constructor() {
    super();
    this.issues = [];
    this._fetchingIssueList = false;
    this._issueListLoaded = false;
    this.selectedIssues = [];
    this._queryParams = {};
    this.columns = [];
    this._usersProjects = new Map();
    this._presentationConfigLoaded = false;

    this._boundRefresh = this.refresh.bind(this);

    this._actions = [
      {icon: 'edit', text: 'Bulk edit', handler: this.bulkEdit.bind(this)},
      {
        icon: 'add', text: 'Add to hotlist',
        handler: this.addToHotlist.bind(this),
      },
      {
        icon: 'table_chart', text: 'Change columns',
        handler: this.openColumnsDialog.bind(this),
      },
      {icon: 'more_vert', text: 'More actions...', items: [
        {text: 'Flag as spam', handler: () => this._flagIssues(true)},
        {text: 'Un-flag as spam', handler: () => this._flagIssues(false)},
      ]},
    ];

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

    // Expose page.js for test stubbing.
    this.page = page;
  };

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

    window.addEventListener('refreshList', this._boundRefresh);

    // TODO(zhangtiff): Consider if we can make this page title more useful for
    // the list view.
    store.dispatch(sitewide.setPageTitle('Issues'));
  }

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

    window.removeEventListener('refreshList', this._boundRefresh);

    this._hideIssueLoadingSnackbar();
  }

  /** @override */
  updated(changedProperties) {
    this._measureIssueListLoadTime(changedProperties);

    if (changedProperties.has('_fetchingIssueList')) {
      const wasFetching = changedProperties.get('_fetchingIssueList');
      const isFetching = this._fetchingIssueList;
      // Show a snackbar if waiting for issues to load but only when there's
      // already a different, non-empty issue list loaded. This approach avoids
      // clearing the issue list for a loading screen.
      if (isFetching && this.totalIssues > 0) {
        this._showIssueLoadingSnackbar();
      }
      if (wasFetching && !isFetching) {
        this._hideIssueLoadingSnackbar();
      }
    }

    if (changedProperties.has('userDisplayName')) {
      store.dispatch(issueV0.fetchStarredIssues());
    }

    if (changedProperties.has('_fetchIssueListError') &&
        this._fetchIssueListError) {
      this._showIssueErrorSnackbar(this._fetchIssueListError);
    }

    const shouldRefresh = this._shouldRefresh(changedProperties);
    if (shouldRefresh) this.refresh();
  }

  /**
   * Tracks the start and end times of an issues list render and
   * records an issue list load time.
   * @param {Map} changedProperties
  */
  async _measureIssueListLoadTime(changedProperties) {
    if (!changedProperties.has('issues')) {
      return;
    }

    if (!changedProperties.get('issues')) {
      // Ignore initial initialization from the constructer where
      // 'issues' is set from undefined to an empty array.
      return;
    }

    const fullAppLoad = ui.navigationCount(store.getState()) == 1;
    const startMark = fullAppLoad ? undefined : 'start load issue list page';

    await Promise.all(_subtreeUpdateComplete(this));

    const endMark = 'finish load list of issues';
    performance.mark(endMark);

    const measurementType = fullAppLoad ? 'from outside app' : 'within app';
    const measurementName = `load list of issues (${measurementType})`;
    performance.measure(measurementName, startMark, endMark);

    const measurement = performance.getEntriesByName(
        measurementName)[0].duration;
    window.getTSMonClient().recordIssueListLoadTiming(measurement, fullAppLoad);

    // Be sure to clear this mark even on full page navigation.
    performance.clearMarks('start load issue list page');
    performance.clearMarks(endMark);
    performance.clearMeasures(measurementName);
  }

  /**
   * Considers if list-page should fetch ListIssues
   * @param {Map} changedProperties
   * @return {boolean}
   */
  _shouldRefresh(changedProperties) {
    const wait = shouldWaitForDefaultQuery(this._queryParams);
    if (wait && !this._presentationConfigLoaded) {
      return false;
    } else if (wait && this._presentationConfigLoaded &&
        changedProperties.has('_presentationConfigLoaded')) {
      return true;
    } else if (changedProperties.has('projectName') ||
          changedProperties.has('currentQuery') ||
          changedProperties.has('currentCan')) {
      return true;
    } else if (changedProperties.has('_queryParams')) {
      const oldParams = changedProperties.get('_queryParams') || {};

      const shouldRefresh = PARAMS_THAT_TRIGGER_REFRESH.some((param) => {
        const oldValue = oldParams[param];
        const newValue = this._queryParams[param];
        return oldValue !== newValue;
      });
      return shouldRefresh;
    }
    return false;
  }

  // TODO(crbug.com/monorail/6933): Remove the need for this wrapper.
  /** Dispatches a Redux action to show an issues loading snackbar.  */
  _showIssueLoadingSnackbar() {
    store.dispatch(ui.showSnackbar(ui.snackbarNames.FETCH_ISSUE_LIST,
        SNACKBAR_LOADING, 0));
  }

  /** Dispatches a Redux action to hide the issue loading snackbar.  */
  _hideIssueLoadingSnackbar() {
    store.dispatch(ui.hideSnackbar(ui.snackbarNames.FETCH_ISSUE_LIST));
  }

  /**
   * Shows a snackbar telling the user their issue loading failed.
   * @param {string} error The error to display.
   */
  _showIssueErrorSnackbar(error) {
    store.dispatch(ui.showSnackbar(ui.snackbarNames.FETCH_ISSUE_LIST_ERROR,
        error));
  }

  /**
   * Refreshes the list of issues show.
   */
  refresh() {
    store.dispatch(issueV0.fetchIssueList(this.projectName, {
      ...this._queryParams,
      q: this.currentQuery,
      can: this.currentCan,
      maxItems: this.maxItems,
      start: this.startIndex,
    }));
  }

  /** @override */
  stateChanged(state) {
    this.projectName = projectV0.viewedProjectName(state);
    this._isLoggedIn = userV0.isLoggedIn(state);
    this._currentUser = userV0.currentUser(state);
    this._usersProjects = userV0.projectsPerUser(state);

    this.issues = issueV0.issueList(state) || [];
    this.totalIssues = issueV0.totalIssues(state) || 0;
    this._fetchingIssueList = issueV0.requests(state).fetchIssueList.requesting;
    this._issueListLoaded = issueV0.issueListLoaded(state);

    const error = issueV0.requests(state).fetchIssueList.error;
    this._fetchIssueListError = error ? error.message : '';

    this.currentQuery = sitewide.currentQuery(state);
    this.currentCan = sitewide.currentCan(state);
    this.columns =
        sitewide.currentColumns(state) || projectV0.defaultColumns(state);

    this._queryParams = sitewide.queryParams(state);

    this._extractFieldValues = projectV0.extractFieldValuesFromIssue(state);
    this._presentationConfigLoaded =
      projectV0.viewedPresentationConfigLoaded(state);
  }

  /**
   * @return {string} Display text of total issue number.
   */
  get totalIssuesDisplay() {
    if (this.totalIssues === 1) {
      return `${this.totalIssues}`;
    } else if (this.totalIssues === SERVER_LIST_ISSUES_LIMIT) {
      // Server has hard limit up to 100,000 list results
      return `100,000+`;
    }
    return `${this.totalIssues}`;
  }

  /**
   * @return {boolean} Whether the user is able to star the issues in the list.
   */
  get starringEnabled() {
    return this._isLoggedIn;
  }

  /**
   * @return {boolean} Whether the user has permissions to edit the issues in
   *   the list.
   */
  get editingEnabled() {
    return this._isLoggedIn && (userIsMember(this._currentUser,
        this.projectName, this._usersProjects) ||
        this._currentUser.isSiteAdmin);
  }

  /**
   * @return {Array<string>} Array of columns to group by.
   */
  get groups() {
    return parseColSpec(this._queryParams.groupby);
  }

  /**
   * @return {number} Maximum number of issues to load for this query.
   */
  get maxItems() {
    return Number.parseInt(this._queryParams.num) || DEFAULT_ISSUES_PER_PAGE;
  }

  /**
   * @return {number} Number of issues to offset by, based on pagination.
   */
  get startIndex() {
    const num = Number.parseInt(this._queryParams.start) || 0;
    return Math.max(0, num);
  }

  /**
   * Computes the current URL of the page with updated queryParams.
   *
   * @param {Object} newParams keys and values to override existing parameters.
   * @return {string} the new URL.
   */
  _urlWithNewParams(newParams) {
    const baseUrl = `/p/${this.projectName}/issues/list`;
    return urlWithNewParams(baseUrl, this._queryParams, newParams);
  }

  /**
   * Shows the user an alert telling them their action won't work.
   * @param {string} action Text describing what you're trying to do.
   */
  noneSelectedAlert(action) {
    // TODO(zhangtiff): Replace this with a modal for a more modern feel.
    alert(`Please select some issues to ${action}.`);
  }

  /**
   * Opens the the column selector.
   */
  openColumnsDialog() {
    this.shadowRoot.querySelector('mr-change-columns').open();
  }

  /**
   * Opens a modal to add the selected issues to a hotlist.
   */
  addToHotlist() {
    const issues = this.selectedIssues;
    if (!issues || !issues.length) {
      this.noneSelectedAlert('add to hotlists');
      return;
    }
    this.shadowRoot.querySelector('mr-update-issue-hotlists-dialog').open();
  }

  /**
   * Redirects the user to the bulk edit page for the issues they've selected.
   */
  bulkEdit() {
    const issues = this.selectedIssues;
    if (!issues || !issues.length) {
      this.noneSelectedAlert('edit');
      return;
    }
    const params = {
      ids: issues.map((issue) => issue.localId).join(','),
      q: this._queryParams && this._queryParams.q,
    };
    this.page(`/p/${this.projectName}/issues/bulkedit?${qs.stringify(params)}`);
  }

  /** Shows user confirmation that their hotlist changes were saved. */
  _showHotlistSaveSnackbar() {
    store.dispatch(ui.showSnackbar(ui.snackbarNames.UPDATE_HOTLISTS_SUCCESS,
        'Hotlists updated.'));
  }

  /**
   * Flags the selected issues as spam.
   * @param {boolean} flagAsSpam If true, flag as spam. If false, unflag
   *   as spam.
   */
  async _flagIssues(flagAsSpam = true) {
    const issues = this.selectedIssues;
    if (!issues || !issues.length) {
      return this.noneSelectedAlert(
          `${flagAsSpam ? 'flag' : 'un-flag'} as spam`);
    }
    const refs = issues.map((issue) => ({
      localId: issue.localId,
      projectName: issue.projectName,
    }));

    // TODO(zhangtiff): Refactor this into a shared action creator and
    // display the error on the frontend.
    try {
      await prpcClient.call('monorail.Issues', 'FlagIssues', {
        issueRefs: refs,
        flag: flagAsSpam,
      });
      this.refresh();
    } catch (e) {
      console.error(e);
    }
  }

  /**
   * Syncs this component's selected issues with the child component's selected
   * issues.
   */
  _setSelectedIssues() {
    const issueListRef = this.shadowRoot.querySelector('mr-issue-list');
    if (!issueListRef) return;

    this.selectedIssues = issueListRef.selectedIssues;
  }
};


/**
 * Recursively traverses all shadow DOMs in an element subtree and returns an
 * Array containing the updateComplete Promises for all lit-element nodes.
 * @param {!LitElement} element
 * @return {!Array<Promise<Boolean>>}
 */
function _subtreeUpdateComplete(element) {
  if (!(element.shadowRoot && element.updateComplete)) {
    return [];
  }

  const children = element.shadowRoot.querySelectorAll('*');
  const childPromises = Array.from(children, (e) => _subtreeUpdateComplete(e));
  return [element.updateComplete].concat(...childPromises);
}

customElements.define('mr-list-page', MrListPage);
