// 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 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);
