// 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 {connectStore} from 'reducers/base.js';
import * as userV0 from 'reducers/userV0.js';
import * as projectV0 from 'reducers/projectV0.js';
import * as sitewide from 'reducers/sitewide.js';

import {prpcClient} from 'prpc-client-instance.js';
import 'elements/framework/mr-keystrokes/mr-keystrokes.js';
import '../mr-dropdown/mr-dropdown.js';
import '../mr-dropdown/mr-account-dropdown.js';
import './mr-search-bar.js';

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

import {logEvent} from 'monitoring/client-logger.js';

/**
 * @type {Object<string, string>} JS coding of enum values from
 *    appengine/monorail/api/v3/api_proto/project_objects.proto.
 */
const projectRoles = Object.freeze({
  OWNER: 'Owner',
  MEMBER: 'Member',
  CONTRIBUTOR: 'Contributor',
  NONE: '',
});

/**
 * `<mr-header>`
 *
 * The header for Monorail.
 *
 */
export class MrHeader extends connectStore(LitElement) {
  /** @override */
  static get styles() {
    return [
      SHARED_STYLES,
      css`
        :host {
          color: var(--chops-header-text-color);
          box-sizing: border-box;
          background: hsl(221, 67%, 92%);
          width: 100%;
          height: var(--monorail-header-height);
          display: flex;
          flex-direction: row;
          justify-content: flex-start;
          align-items: center;
          z-index: 800;
          background-color: var(--chops-primary-header-bg);
          border-bottom: var(--chops-normal-border);
          top: 0;
          position: fixed;
          padding: 0 4px;
          font-size: var(--chops-large-font-size);
        }
        @media (max-width: 840px) {
          :host {
            position: static;
          }
        }
        a {
          font-size: inherit;
          color: var(--chops-link-color);
          text-decoration: none;
          display: flex;
          align-items: center;
          justify-content: center;
          height: 100%;
          padding: 0 4px;
          flex-grow: 0;
          flex-shrink: 0;
        }
        a[hidden] {
          display: none;
        }
        a.button {
          font-size: inherit;
          height: auto;
          margin: 0 8px;
          border: 0;
          height: 30px;
        }
        .home-link {
          color: var(--chops-gray-900);
          letter-spacing: 0.5px;
          font-size: 18px;
          font-weight: 400;
          display: flex;
          font-stretch: 100%;
          padding-left: 8px;
        }
        a.home-link img {
          /** Cover up default padding with the custom logo. */
          margin-left: -8px;
        }
        a.home-link:hover {
          text-decoration: none;
        }
        mr-search-bar {
          margin-left: 8px;
          flex-grow: 2;
          max-width: 1000px;
        }
        i.material-icons {
          font-size: var(--chops-icon-font-size);
          color: var(--chops-primary-icon-color);
        }
        i.material-icons[hidden] {
          display: none;
        }
        .right-section {
          font-size: inherit;
          display: flex;
          align-items: center;
          height: 100%;
          margin-left: auto;
          justify-content: flex-end;
        }
        .hamburger-icon:hover {
          text-decoration: none;
        }
      `,
    ];
  }

  /** @override */
  render() {
    return this.projectName ?
        this._renderProjectScope() : this._renderNonProjectScope();
  }

  /**
   * @return {TemplateResult}
   */
  _renderProjectScope() {
    return html`
      <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
      <mr-keystrokes
        .issueId=${this.queryParams.id}
        .queryParams=${this.queryParams}
        .issueEntryUrl=${this.issueEntryUrl}
      ></mr-keystrokes>
      <a href="/p/${this.projectName}/issues/list" class="home-link">
        ${this.projectThumbnailUrl ? html`
          <img
            class="project-logo"
            src=${this.projectThumbnailUrl}
            title=${this.projectName}
          />
        ` : this.projectName}
      </a>
      <mr-dropdown
        class="project-selector"
        .text=${this.projectName}
        .items=${this._projectDropdownItems}
        menuAlignment="left"
        title=${this.presentationConfig.projectSummary}
      ></mr-dropdown>
      <a class="button emphasized new-issue-link" href=${this.issueEntryUrl}>
        New issue
      </a>
      <mr-search-bar
        .projectName=${this.projectName}
        .userDisplayName=${this.userDisplayName}
        .projectSavedQueries=${this.presentationConfig.savedQueries}
        .initialCan=${this._currentCan}
        .initialQuery=${this._currentQuery}
        .queryParams=${this.queryParams}
      ></mr-search-bar>

      <div class="right-section">
        <mr-dropdown
          icon="settings"
          label="Project Settings"
          .items=${this._projectSettingsItems}
        ></mr-dropdown>

        ${this._renderAccount()}
      </div>
    `;
  }

  /**
   * @return {TemplateResult}
   */
  _renderNonProjectScope() {
    return html`
      <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
      <a class="hamburger-icon" title="Main menu" hidden>
        <i class="material-icons">menu</i>
      </a>
      ${this._headerTitle ?
          html`<span class="home-link">${this._headerTitle}</span>` :
          html`<a href="/" class="home-link">Monorail</a>`}

      <div class="right-section">
        ${this._renderAccount()}
      </div>
    `;
  }

  /**
   * @return {TemplateResult}
   */
  _renderAccount() {
    if (!this.userDisplayName) {
      return html`<a href=${this.loginUrl}>Sign in</a>`;
    }

    return html`
      <mr-account-dropdown
        .userDisplayName=${this.userDisplayName}
        .logoutUrl=${this.logoutUrl}
        .loginUrl=${this.loginUrl}
      ></mr-account-dropdown>
    `;
  }

  /** @override */
  static get properties() {
    return {
      loginUrl: {type: String},
      logoutUrl: {type: String},
      projectName: {type: String},
      // Project thumbnail is set separately from presentationConfig to prevent
      // "flashing" logo when navigating EZT pages.
      projectThumbnailUrl: {type: String},
      userDisplayName: {type: String},
      isSiteAdmin: {type: Boolean},
      userProjects: {type: Object},
      presentationConfig: {type: Object},
      queryParams: {type: Object},
      // TODO(zhangtiff): Change this to be dynamically computed by the
      //   frontend with logic similar to ComputeIssueEntryURL().
      issueEntryUrl: {type: String},
      clientLogger: {type: Object},
      _headerTitle: {type: String},
      _currentQuery: {type: String},
      _currentCan: {type: String},
    };
  }

  /** @override */
  constructor() {
    super();

    this.presentationConfig = {};
    this.userProjects = {};
    this.isSiteAdmin = false;

    this._headerTitle = '';
  }

  /** @override */
  stateChanged(state) {
    this.projectName = projectV0.viewedProjectName(state);

    this.userProjects = userV0.projects(state);

    const currentUser = userV0.currentUser(state);
    this.isSiteAdmin = currentUser ? currentUser.isSiteAdmin : false;

    const presentationConfig = projectV0.viewedPresentationConfig(state);
    this.presentationConfig = presentationConfig;
    // Set separately in order allow EZT pages to load project logo before
    // the GetPresentationConfig pRPC request.
    this.projectThumbnailUrl = presentationConfig.projectThumbnailUrl;

    this._headerTitle = sitewide.headerTitle(state);

    this._currentQuery = sitewide.currentQuery(state);
    this._currentCan = sitewide.currentCan(state);

    this.queryParams = sitewide.queryParams(state);
  }

  /**
   * @return {boolean} whether the currently logged in user has admin
   *   privileges for the currently viewed project.
   */
  get canAdministerProject() {
    if (!this.userDisplayName) return false; // Not logged in.
    if (this.isSiteAdmin) return true;
    if (!this.userProjects || !this.userProjects.ownerOf) return false;
    return this.userProjects.ownerOf.includes(this.projectName);
  }

  /**
   * @return {string} The name of the role the user has in the viewed project.
   */
  get roleInCurrentProject() {
    if (!this.userProjects || !this.projectName) return projectRoles.NONE;
    const {ownerOf = [], memberOf = [], contributorTo = []} = this.userProjects;

    if (ownerOf.includes(this.projectName)) return projectRoles.OWNER;
    if (memberOf.includes(this.projectName)) return projectRoles.MEMBER;
    if (contributorTo.includes(this.projectName)) {
      return projectRoles.CONTRIBUTOR;
    }

    return projectRoles.NONE;
  }

  // TODO(crbug.com/monorail/6891): Remove once we deprecate the old issue
  // filing wizard.
  /**
   * @return {string} A URL for the page the issue filing wizard posts to.
   */
  get _wizardPostUrl() {
    // The issue filing wizard posts to the legacy issue entry page's ".do"
    // endpoint.
    return `${this._origin}/p/${this.projectName}/issues/entry.do`;
  }

  /**
   * @return {string} The domain name of the current page.
   */
  get _origin() {
    return window.location.origin;
  }

  /**
   * Computes the URL the user should see to a file an issue, accounting
   * for the case where a project has a customIssueEntryUrl to navigate to
   * the wizard as well.
   * @return {string} The URL that "New issue" button goes to.
   */
  get issueEntryUrl() {
    const config = this.presentationConfig;
    const role = this.roleInCurrentProject;
    const mayBeRedirectedToWizard = role === projectRoles.NONE;
    if (!this.userDisplayName || !config || !config.customIssueEntryUrl ||
        !mayBeRedirectedToWizard) {
      return `/p/${this.projectName}/issues/entry`;
    }

    const token = prpcClient.token;

    const customUrl = this.presentationConfig.customIssueEntryUrl;

    return `${customUrl}?token=${token}&role=${
      role}&continue=${this._wizardPostUrl}`;
  }

  /**
   * @return {Array<MenuItem>} the dropdown items for the project selector,
   *   showing which projects a user can switch to.
   */
  get _projectDropdownItems() {
    const {userProjects, loginUrl} = this;
    if (!this.userDisplayName) {
      return [{text: 'Sign in to see your projects', url: loginUrl}];
    }

    const items = [];
    const starredProjects = userProjects.starredProjects || [];
    const projects = (userProjects.ownerOf || [])
        .concat(userProjects.memberOf || [])
        .concat(userProjects.contributorTo || []);

    if (projects.length) {
      projects.sort();
      items.push({text: 'My Projects', separator: true});

      projects.forEach((project) => {
        items.push({text: project, url: `/p/${project}/issues/list`});
      });
    }

    if (starredProjects.length) {
      starredProjects.sort();
      items.push({text: 'Starred Projects', separator: true});

      starredProjects.forEach((project) => {
        items.push({text: project, url: `/p/${project}/issues/list`});
      });
    }

    if (items.length) {
      items.push({separator: true});
    }

    items.push({text: 'All projects', url: '/hosting/'});
    items.forEach((item) => {
      item.handler = () => this._projectChangedHandler(item.url);
    });
    return items;
  }

  /**
   * @return {Array<MenuItem>} dropdown menu items to show in the project
   *   settings menu.
   */
  get _projectSettingsItems() {
    const {projectName, canAdministerProject} = this;
    const items = [
      {text: 'People', url: `/p/${projectName}/people/list`},
      {text: 'Development Process', url: `/p/${projectName}/adminIntro`},
      {text: 'History', url: `/p/${projectName}/updates/list`},
    ];

    if (canAdministerProject) {
      items.push({separator: true});
      items.push({text: 'Administer', url: `/p/${projectName}/admin`});
    }
    return items;
  }

  /**
   * Records Google Analytics events for when users change projects using
   * the selector.
   * @param {string} url which project URL the user is navigating to.
   */
  _projectChangedHandler(url) {
    // Just log it to GA and continue.
    logEvent('mr-header', 'project-change', url);
  }
}

customElements.define('mr-header', MrHeader);
