// 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 {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 {generateProjectIssueURL} from 'shared/helpers.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="${generateProjectIssueURL(this.projectName, '/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">avm99963 bugs</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 generateProjectIssueURL(this.projectName, '/entry');
    }
    //TODO(monorail/12012) redirec to tracker once new chromium wizard is ready.
    return `/p/${this.projectName}/issues/wizard`;
  }

  /**
   * @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: generateProjectIssueURL(project, '/list')});
      });
    }

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

      starredProjects.forEach((project) => {
        items.push({text: project, url: generateProjectIssueURL(project, '/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);
