// 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} from 'lit-element';
import {repeat} from 'lit-html/directives/repeat';
import page from 'page';
import qs from 'qs';

import {getServerStatusCron} from 'shared/cron.js';
import 'elements/framework/mr-site-banner/mr-site-banner.js';
import {store, connectStore} from 'reducers/base.js';
import * as projectV0 from 'reducers/projectV0.js';
import {hotlists} from 'reducers/hotlists.js';
import * as issueV0 from 'reducers/issueV0.js';
import * as permissions from 'reducers/permissions.js';
import * as users from 'reducers/users.js';
import * as userv0 from 'reducers/userV0.js';
import * as ui from 'reducers/ui.js';
import * as sitewide from 'reducers/sitewide.js';
import {arrayToEnglish} from 'shared/helpers.js';
import {trackPageChange} from 'shared/ga-helpers.js';
import 'elements/chops/chops-announcement/chops-announcement.js';
import 'elements/issue-list/mr-list-page/mr-list-page.js';
import 'elements/issue-entry/mr-issue-entry-page.js';
import 'elements/framework/mr-header/mr-header.js';
import 'elements/help/mr-cue/mr-cue.js';
import {cueNames} from 'elements/help/mr-cue/cue-helpers.js';
import 'elements/chops/chops-snackbar/chops-snackbar.js';

import {SHARED_STYLES} from 'shared/shared-styles.js';

const QUERY_PARAMS_THAT_RESET_SCROLL = ['q', 'mode', 'id'];

/**
 * `<mr-app>`
 *
 * The container component for all pages under the Monorail SPA.
 *
 */
export class MrApp extends connectStore(LitElement) {
  /** @override */
  render() {
    if (this.page === 'wizard') {
      return html`<div id="reactMount"></div>`;
    }

    return html`
      <style>
        ${SHARED_STYLES}
        mr-app {
          display: block;
          padding-top: var(--monorail-header-height);
          margin-top: -1px; /* Prevent a double border from showing up. */

          /* From shared-styles.js. */
          --mr-edit-field-padding: 0.125em 4px;
          --mr-edit-field-width: 90%;
          --mr-input-grid-gap: 6px;
          font-family: var(--chops-font-family);
          color: var(--chops-primary-font-color);
          font-size: var(--chops-main-font-size);
        }
        main {
          border-top: var(--chops-normal-border);
        }
        .snackbar-container {
          position: fixed;
          bottom: 1em;
          left: 1em;
          display: flex;
          flex-direction: column;
          align-items: flex-start;
          z-index: 1000;
        }
        /** Unfix <chops-snackbar> to allow stacking. */
        chops-snackbar {
          position: static;
          margin-top: 0.5em;
        }
      </style>
      <mr-header
        .userDisplayName=${this.userDisplayName}
        .loginUrl=${this.loginUrl}
        .logoutUrl=${this.logoutUrl}
      ></mr-header>
      <chops-announcement service="monorail"></chops-announcement>
      <mr-site-banner></mr-site-banner>
      <mr-cue
        cuePrefName=${cueNames.SWITCH_TO_PARENT_ACCOUNT}
        .loginUrl=${this.loginUrl}
        centered
        nondismissible
      ></mr-cue>
      <mr-cue
        cuePrefName=${cueNames.SEARCH_FOR_NUMBERS}
        centered
      ></mr-cue>
      <main>${this._renderPage()}</main>
      <div class="snackbar-container" aria-live="polite">
        ${repeat(this._snackbars, (snackbar) => html`
          <chops-snackbar
            @close=${this._closeSnackbar.bind(this, snackbar.id)}
          >${snackbar.text}</chops-snackbar>
        `)}
      </div>
    `;
  }

  /**
   * @param {string} id The name of the snackbar to close.
   */
  _closeSnackbar(id) {
    store.dispatch(ui.hideSnackbar(id));
  }

  /**
   * Helper for determiing which page component to render.
   * @return {TemplateResult}
   */
  _renderPage() {
    switch (this.page) {
      case 'detail':
        return html`
          <mr-issue-page
            .userDisplayName=${this.userDisplayName}
            .loginUrl=${this.loginUrl}
          ></mr-issue-page>
        `;
      case 'entry':
        return html`
          <mr-issue-entry-page
            .userDisplayName=${this.userDisplayName}
            .loginUrl=${this.loginUrl}
          ></mr-issue-entry-page>
        `;
      case 'grid':
        return html`
          <mr-grid-page
            .userDisplayName=${this.userDisplayName}
          ></mr-grid-page>
        `;
      case 'list':
        return html`
          <mr-list-page
            .userDisplayName=${this.userDisplayName}
          ></mr-list-page>
        `;
      case 'chart':
        return html`<mr-chart-page></mr-chart-page>`;
      case 'projects':
        return html`<mr-projects-page></mr-projects-page>`;
      case 'hotlist-issues':
        return html`<mr-hotlist-issues-page></mr-hotlist-issues-page>`;
      case 'hotlist-people':
        return html`<mr-hotlist-people-page></mr-hotlist-people-page>`;
      case 'hotlist-settings':
        return html`<mr-hotlist-settings-page></mr-hotlist-settings-page>`;
      default:
        return;
    }
  }

  /** @override */
  static get properties() {
    return {
      /**
       * Backend-generated URL for the page the user is directed to for login.
       */
      loginUrl: {type: String},
      /**
       * Backend-generated URL for the page the user is directed to for logout.
       */
      logoutUrl: {type: String},
      /**
       * The display name of the currently logged in user.
       */
      userDisplayName: {type: String},
      /**
       * The search parameters in the user's current URL.
       */
      queryParams: {type: Object},
      /**
       * A list of forms to check for "dirty" values when the user navigates
       * across pages.
       */
      dirtyForms: {type: Array},
      /**
       * App Engine ID for the current version being viewed.
       */
      versionBase: {type: String},
      /**
       * A String identifier for the page that the user is viewing.
       */
      page: {type: String},
      /**
       * A String for the title of the page that the user will see in their
       * browser tab. ie: equivalent to the <title> tag.
       */
      pageTitle: {type: String},
      /**
       * Array of snackbar objects to render.
       */
      _snackbars: {type: Array},
    };
  }

  /** @override */
  constructor() {
    super();
    this.queryParams = {};
    this.dirtyForms = [];
    this.userDisplayName = '';

    /**
     * @type {PageJS.Context}
     * The context of the page. This should not be a LitElement property
     * because we don't want to re-render when updating this.
     */
    this._lastContext = undefined;
  }

  /** @override */
  createRenderRoot() {
    return this;
  }

  /** @override */
  stateChanged(state) {
    this.dirtyForms = ui.dirtyForms(state);
    this.queryParams = sitewide.queryParams(state);
    this.pageTitle = sitewide.pageTitle(state);
    this._snackbars = ui.snackbars(state);
  }

  /** @override */
  updated(changedProperties) {
    if (changedProperties.has('userDisplayName') && this.userDisplayName) {
      // TODO(https://crbug.com/monorail/7238): Migrate userv0 calls to v3 API.
      store.dispatch(userv0.fetch(this.userDisplayName));

      // Typically we would prefer 'users/<userId>' instead.
      store.dispatch(users.fetch(`users/${this.userDisplayName}`));
    }

    if (changedProperties.has('pageTitle')) {
      // To ensure that changes to the page title are easy to reason about,
      // we want to sync the current pageTitle in the Redux state to
      // document.title in only one place in the code.
      document.title = this.pageTitle;
    }
    if (changedProperties.has('page')) {
      trackPageChange(this.page, this.userDisplayName);
    }
  }

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

    // TODO(zhangtiff): Figure out some way to save Redux state between
    // page loads.

    // page doesn't handle users reloading the page or closing a tab.
    window.onbeforeunload = this._confirmDiscardMessage.bind(this);

    // Start a cron task to periodically request the status from the server.
    getServerStatusCron.start();

    const postRouteHandler = this._postRouteHandler.bind(this);

    // Populate the project route parameter before _preRouteHandler runs.
    page('/p/:project/*', (_ctx, next) => next());
    page('*', this._preRouteHandler.bind(this));

    page('/hotlists/:hotlist', (ctx) => {
      page.redirect(`/hotlists/${ctx.params.hotlist}/issues`);
    });
    page('/hotlists/:hotlist/*', this._selectHotlist);
    page('/hotlists/:hotlist/issues',
        this._loadHotlistIssuesPage.bind(this), postRouteHandler);
    page('/hotlists/:hotlist/people',
        this._loadHotlistPeoplePage.bind(this), postRouteHandler);
    page('/hotlists/:hotlist/settings',
        this._loadHotlistSettingsPage.bind(this), postRouteHandler);

    // Handle Monorail's landing page.
    page('/p', '/');
    page('/projects', '/');
    page('/hosting', '/');
    page('/', this._loadProjectsPage.bind(this), postRouteHandler);

    page('/p/:project/issues/list', this._loadListPage.bind(this),
        postRouteHandler);
    page('/p/:project/issues/detail', this._loadIssuePage.bind(this),
        postRouteHandler);
    page('/p/:project/issues/entry_new', this._loadEntryPage.bind(this),
        postRouteHandler);
    page('/p/:project/issues/wizard', this._loadWizardPage.bind(this),
        postRouteHandler);

    // Redirects from old hotlist pages to SPA hotlist pages.
    const hotlistRedirect = (pageName) => async (ctx) => {
      const name =
          await hotlists.getHotlistName(ctx.params.user, ctx.params.hotlist);
      page.redirect(`/${name}/${pageName}`);
    };
    page('/users/:user/hotlists/:hotlist', hotlistRedirect('issues'));
    page('/users/:user/hotlists/:hotlist/people', hotlistRedirect('people'));
    page('/users/:user/hotlists/:hotlist/details', hotlistRedirect('settings'));

    page();
  }

  /**
   * Handler that runs on every single route change, before the new page has
   * loaded. This function should not use store.dispatch() or assign properties
   * on this because running these actions causes extra re-renders to happen.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  _preRouteHandler(ctx, next) {
    // We're not really navigating anywhere, so don't do anything.
    if (this._lastContext && this._lastContext.path &&
      ctx.path === this._lastContext.path) {
      Object.assign(ctx, this._lastContext);
      // Set ctx.handled to false, so we don't push the state to browser's
      // history.
      ctx.handled = false;
      return;
    }

    // Check if there were forms with unsaved data before loading the next
    // page.
    const discardMessage = this._confirmDiscardMessage();
    if (discardMessage && !confirm(discardMessage)) {
      Object.assign(ctx, this._lastContext);
      // Set ctx.handled to false, so we don't push the state to browser's
      // history.
      ctx.handled = false;
      // We don't call next to avoid loading whatever page was supposed to
      // load next.
      return;
    }

    // Run query string parsing on all routes. Query params must be parsed
    // before routes are loaded because some routes use them to conditionally
    // load bundles.
    // Based on: https://visionmedia.github.io/page.js/#plugins
    const params = qs.parse(ctx.querystring);

    // Make sure queryParams are not case sensitive.
    const lowerCaseParams = {};
    Object.keys(params).forEach((key) => {
      lowerCaseParams[key.toLowerCase()] = params[key];
    });
    ctx.queryParams = lowerCaseParams;

    this._selectProject(ctx.params.project);

    next();
  }

  /**
   * Handler that runs on every single route change, after the new page has
   * loaded.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  _postRouteHandler(ctx, next) {
    // Scroll to the requested element if a hash is present.
    if (ctx.hash) {
      store.dispatch(ui.setFocusId(ctx.hash));
    }

    // Sync queryParams to Redux after the route has loaded, rather than before,
    // to avoid having extra queryParams update on the previously loaded
    // component.
    store.dispatch(sitewide.setQueryParams(ctx.queryParams));

    // Increment the count of navigations in the Redux store.
    store.dispatch(ui.incrementNavigationCount());

    // Clear dirty forms when entering a new page.
    store.dispatch(ui.clearDirtyForms());


    if (!this._lastContext || this._lastContext.pathname !== ctx.pathname ||
        this._hasReleventParamChanges(ctx.queryParams,
            this._lastContext.queryParams)) {
      // Reset the scroll position after a new page has rendered.
      window.scrollTo(0, 0);
    }

    // Save the context of this page to be compared to later.
    this._lastContext = ctx;
  }

  /**
   * Finds if a route change changed query params in a way that should cause
   * scrolling to reset.
   * @param {Object} currentParams
   * @param {Object} oldParams
   * @param {Array<string>=} paramsToCompare Which params to check.
   * @return {boolean} Whether any of the relevant query params changed.
   */
  _hasReleventParamChanges(currentParams, oldParams,
      paramsToCompare = QUERY_PARAMS_THAT_RESET_SCROLL) {
    return paramsToCompare.some((paramName) => {
      return currentParams[paramName] !== oldParams[paramName];
    });
  }

  /**
   * Helper to manage syncing project route state to Redux.
   * @param {string=} project displayName for a referenced project.
   *   Defaults to null for consistency with Redux.
   */
  _selectProject(project = null) {
    if (projectV0.viewedProjectName(store.getState()) !== project) {
      // Note: We want to update the project even if the new project
      // is null.
      store.dispatch(projectV0.select(project));
      if (project) {
        store.dispatch(projectV0.fetch(project));
      }
    }
  }

  /**
   * Loads and triggers rendering for the list of all projects.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  async _loadProjectsPage(ctx, next) {
    await import(/* webpackChunkName: "mr-projects-page" */
        '../projects/mr-projects-page/mr-projects-page.js');
    this.page = 'projects';
    next();
  }

  /**
   * Loads and triggers render for the issue detail page.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  async _loadIssuePage(ctx, next) {
    performance.clearMarks('start load issue detail page');
    performance.mark('start load issue detail page');

    await import(/* webpackChunkName: "mr-issue-page" */
        '../issue-detail/mr-issue-page/mr-issue-page.js');

    const issueRef = {
      localId: Number.parseInt(ctx.queryParams.id),
      projectName: ctx.params.project,
    };
    store.dispatch(issueV0.viewIssue(issueRef));
    store.dispatch(issueV0.fetchIssuePageData(issueRef));
    this.page = 'detail';
    next();
  }

  /**
   * Loads and triggers render for the issue list page, including the list,
   * grid, and chart modes.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  async _loadListPage(ctx, next) {
    performance.clearMarks('start load issue list page');
    performance.mark('start load issue list page');
    switch (ctx.queryParams && ctx.queryParams.mode &&
        ctx.queryParams.mode.toLowerCase()) {
      case 'grid':
        await import(/* webpackChunkName: "mr-grid-page" */
            '../issue-list/mr-grid-page/mr-grid-page.js');
        this.page = 'grid';
        break;
      case 'chart':
        await import(/* webpackChunkName: "mr-chart-page" */
            '../issue-list/mr-chart-page/mr-chart-page.js');
        this.page = 'chart';
        break;
      default:
        this.page = 'list';
        break;
    }
    next();
  }

  /**
   * Load the issue entry page
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  _loadEntryPage(ctx, next) {
    this.page = 'entry';
    next();
  }

  /**
   * Load the issue wizard
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  async _loadWizardPage(ctx, next) {
    const {renderWizard} = await import(
        /* webpackChunkName: "IssueWizard" */ '../../react/IssueWizard.tsx');

    this.page = 'wizard';
    next();

    await this.updateComplete;

    const mount = document.getElementById('reactMount');

    renderWizard(mount);
  }

  /**
   * Gets the currently viewed HotlistRef from the URL, selects
   * it in the Redux store, and fetches the Hotlist data.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  _selectHotlist(ctx, next) {
    const name = 'hotlists/' + ctx.params.hotlist;
    store.dispatch(hotlists.select(name));
    store.dispatch(hotlists.fetch(name));
    store.dispatch(hotlists.fetchItems(name));
    store.dispatch(permissions.batchGet([name]));
    next();
  }

  /**
   * Loads mr-hotlist-issues-page.js and makes it the currently viewed page.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  async _loadHotlistIssuesPage(ctx, next) {
    await import(/* webpackChunkName: "mr-hotlist-issues-page" */
        `../hotlist/mr-hotlist-issues-page/mr-hotlist-issues-page.js`);
    this.page = 'hotlist-issues';
    next();
  }

  /**
   * Loads mr-hotlist-people-page.js and makes it the currently viewed page.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  async _loadHotlistPeoplePage(ctx, next) {
    await import(/* webpackChunkName: "mr-hotlist-people-page" */
        `../hotlist/mr-hotlist-people-page/mr-hotlist-people-page.js`);
    this.page = 'hotlist-people';
    next();
  }

  /**
   * Loads mr-hotlist-settings-page.js and makes it the currently viewed page.
   * @param {PageJS.Context} ctx A page.js Context containing routing state.
   * @param {function} next Passes execution on to the next registered callback.
   */
  async _loadHotlistSettingsPage(ctx, next) {
    await import(/* webpackChunkName: "mr-hotlist-settings-page" */
        `../hotlist/mr-hotlist-settings-page/mr-hotlist-settings-page.js`);
    this.page = 'hotlist-settings';
    next();
  }

  /**
   * Constructs a message to warn users about dirty forms when they navigate
   * away from a page, to prevent them from loasing data.
   * @return {string} Message shown to users to warn about in flight form
   *   changes.
   */
  _confirmDiscardMessage() {
    if (!this.dirtyForms.length) return null;
    const dirtyFormsMessage =
      'Discard your changes in the following forms?\n' +
      arrayToEnglish(this.dirtyForms);
    return dirtyFormsMessage;
  }
}

customElements.define('mr-app', MrApp);
