// 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} from 'lit-element';

import 'elements/chops/chops-dialog/chops-dialog.js';
import {store, connectStore} from 'reducers/base.js';
import * as issueV0 from 'reducers/issueV0.js';
import * as projectV0 from 'reducers/projectV0.js';
import '../mr-approval-card/mr-approval-card.js';
import {valueForField, valuesForField} from 'shared/metadata-helpers.js';
import 'elements/issue-detail/metadata/mr-edit-metadata/mr-edit-metadata.js';
import 'elements/issue-detail/metadata/mr-metadata/mr-field-values.js';

const TARGET_PHASE_MILESTONE_MAP = {
  'Beta': 'feature_freeze',
  'Stable-Exp': 'final_beta_cut',
  'Stable': 'stable_cut',
  'Stable-Full': 'stable_cut',
};

const APPROVED_PHASE_MILESTONE_MAP = {
  'Beta': 'earliest_beta',
  'Stable-Exp': 'final_beta',
  'Stable': 'stable_date',
  'Stable-Full': 'stable_date',
};

// The following milestones are unique to ios.
const IOS_APPROVED_PHASE_MILESTONE_MAP = {
  'Beta': 'earliest_beta_ios',
};

// See monorail:4692 and the use of PHASES_WITH_MILESTONES
// in tracker/issueentry.py
const PHASES_WITH_MILESTONES = ['Beta', 'Stable', 'Stable-Exp', 'Stable-Full'];

/**
 * `<mr-phase>`
 *
 * This is the component for a single phase.
 *
 */
export class MrPhase extends connectStore(LitElement) {
  /** @override */
  render() {
    const isPhaseWithMilestone = PHASES_WITH_MILESTONES.includes(
        this.phaseName);
    const noApprovals = !this.approvals || !this.approvals.length;
    return html`
      <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
      <style>
        mr-phase {
          display: block;
        }
        mr-phase chops-dialog {
          --chops-dialog-theme: {
            width: 500px;
            max-width: 100%;
          };
        }
        mr-phase h2 {
          margin: 0;
          font-size: var(--chops-large-font-size);
          font-weight: normal;
          padding: 0.5em 8px;
          box-sizing: border-box;
          display: flex;
          align-items: center;
          flex-direction: row;
          justify-content: space-between;
        }
        mr-phase h2 em {
          margin-left: 16px;
          font-size: var(--chops-main-font-size);
        }
        mr-phase .chip {
          display: inline-block;
          font-size: var(--chops-main-font-size);
          padding: 0.25em 8px;
          margin: 0 2px;
          border-radius: 16px;
          background: var(--chops-blue-gray-50);
        }
        .phase-edit {
          padding: 0.1em 8px;
        }
      </style>
      <h2>
        <div>
          Approvals<span ?hidden=${!this.phaseName || !this.phaseName.length}>:
            ${this.phaseName}
          </span>
          ${isPhaseWithMilestone ? html`${this.fieldDefs &&
              this.fieldDefs.map((field) => this._renderPhaseField(field))}
            <em ?hidden=${!this._nextDate}>
              ${this._dateDescriptor}
              <chops-timestamp .timestamp=${this._nextDate}></chops-timestamp>
            </em>
            <em ?hidden=${!this._nextUniqueiOSDate}>
              <b>iOS</b> ${this._dateDescriptor}
              <chops-timestamp .timestamp=${this._nextUniqueiOSDate}
              ></chops-timestamp>
            </em>
          `: ''}
        </div>
        ${isPhaseWithMilestone ? html`
          <chops-button @click=${this.edit} class="de-emphasized phase-edit">
            <i class="material-icons" role="presentation">create</i>
            Edit
          </chops-button>
        `: ''}
      </h2>
      ${this.approvals && this.approvals.map((approval) => html`
        <mr-approval-card
          .approvers=${approval.approverRefs}
          .setter=${approval.setterRef}
          .fieldName=${approval.fieldRef.fieldName}
          .phaseName=${this.phaseName}
          .statusEnum=${approval.status}
          .survey=${approval.survey}
          .surveyTemplate=${approval.surveyTemplate}
          .urls=${approval.urls}
          .labels=${approval.labels}
          .users=${approval.users}
        ></mr-approval-card>
      `)}
      ${noApprovals ? html`No tasks for this phase.` : ''}
      <!-- TODO(ehmaldonado): Move to /issue-detail/dialogs -->
      <chops-dialog id="editPhase" aria-labelledby="phaseDialogTitle">
        <h3 id="phaseDialogTitle" class="medium-heading">
          Editing phase: ${this.phaseName}
        </h3>
        <mr-edit-metadata
          id="metadataForm"
          class="edit-actions-right"
          .formName=${this.phaseName}
          .fieldDefs=${this.fieldDefs}
          .phaseName=${this.phaseName}
          ?disabled=${this._updatingIssue}
          .error=${this._updateIssueError && this._updateIssueError.description}
          @save=${this.save}
          @discard=${this.cancel}
          isApproval
          disableAttachments
        ></mr-edit-metadata>
      </chops-dialog>
    `;
  }

  /**
   *
   * @param {FieldDef} field The field to be rendered.
   * @return {TemplateResult}
   * @private
   */
  _renderPhaseField(field) {
    const values = valuesForField(this._fieldValueMap, field.fieldRef.fieldName,
        this.phaseName);
    return html`
      <div class="chip">
        ${field.fieldRef.fieldName}:
        <mr-field-values
          .name=${field.fieldRef.fieldName}
          .type=${field.fieldRef.type}
          .values=${values}
          .projectName=${this.issueRef.projectName}
        ></mr-field-values>
      </div>
    `;
  }

  /** @override */
  static get properties() {
    return {
      issue: {type: Object},
      issueRef: {type: Object},
      phaseName: {type: String},
      approvals: {type: Array},
      fieldDefs: {type: Array},

      _updatingIssue: {type: Boolean},
      _updateIssueError: {type: Object},
      _fieldValueMap: {type: Object},
      _milestoneData: {type: Object},
      _isFetchingMilestone: {type: Boolean},
      _fetchedMilestone: {type: String},
    };
  }

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

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

    this.issue = {};
    this.issueRef = {};
    this.phaseName = '';
    this.approvals = [];
    this.fieldDefs = [];

    this._updatingIssue = false;
    this._updateIssueError = undefined;

    // A response Object from
    // https://chromiumdash.appspot.com/fetch_milestone_schedule?mstone=xx
    this._milestoneData = {};
    this._isFetchingMilestone = false;
    this._fetchedMilestone = undefined;
    /**
     * @type {Promise} Used for testing to allow waiting for milestone
     *   fetch operations to finish.
     */
    this._fetchMilestoneComplete = undefined;
  }

  /** @override */
  stateChanged(state) {
    this.issue = issueV0.viewedIssue(state);
    this.issueRef = issueV0.viewedIssueRef(state);
    this.fieldDefs = projectV0.fieldDefsForPhases(state);
    this._updatingIssue = issueV0.requests(state).update.requesting;
    this._updateIssueError = issueV0.requests(state).update.error;
    this._fieldValueMap = issueV0.fieldValueMap(state);
  }

  /** @override */
  updated(changedProperties) {
    if (changedProperties.has('issue')) {
      this.reset();
    }
    if (changedProperties.has('_updatingIssue')) {
      if (!this._updatingIssue && !this._updateIssueError) {
        // Close phase edit modal only after a request finishes without errors.
        this.cancel();
      }
    }

    if (!this._isFetchingMilestone) {
      const milestoneToFetch = this._milestoneToFetch;
      if (milestoneToFetch && this._fetchedMilestone !== milestoneToFetch) {
        this._fetchMilestoneComplete = this.fetchMilestoneData(
            milestoneToFetch);
      }
    }
  }

  /**
   * Makes an XHR request to Chromium Dash to find Chrome-specific launch data.
   * eg. when certain Chrome milestones are planned for release.
   * @param {string} milestone A string containing a Chrome milestone number.
   * @return {Promise<void>}
   */
  async fetchMilestoneData(milestone) {
    this._isFetchingMilestone = true;

    try {
      const resp = await window.fetch(
          `https://chromiumdash.appspot.com/fetch_milestone_schedule?mstone=${
            milestone}`);
      this._milestoneData = await resp.json();
    } catch (error) {
      console.error(`Error when fetching milestone data: ${error}`);
    }
    this._fetchedMilestone = milestone;
    this._isFetchingMilestone = false;
  }

  /**
   * Opens the phase editing dialog when the user clicks the edit button.
   */
  edit() {
    this.reset();
    this.querySelector('#editPhase').open();
  }

  /**
   * Stops editing the phase.
   */
  cancel() {
    this.querySelector('#editPhase').close();
    this.reset();
  }

  /**
   * Resets the edit form to its default values.
   */
  reset() {
    const form = this.querySelector('#metadataForm');
    form.reset();
  }

  /**
   * Saves the changes the user has made.
   */
  save() {
    const form = this.querySelector('#metadataForm');
    const delta = form.delta;

    if (delta.fieldValsAdd) {
      delta.fieldValsAdd = delta.fieldValsAdd.map(
          (fv) => Object.assign({phaseRef: {phaseName: this.phaseName}}, fv));
    }
    if (delta.fieldValsRemove) {
      delta.fieldValsRemove = delta.fieldValsRemove.map(
          (fv) => Object.assign({phaseRef: {phaseName: this.phaseName}}, fv));
    }

    const message = {
      issueRef: this.issueRef,
      delta: delta,
      sendEmail: form.sendEmail,
      commentContent: form.getCommentContent(),
    };

    if (message.commentContent || message.delta) {
      store.dispatch(issueV0.update(message));
    }
  }

  /**
   * Shows the next relevant Chrome Milestone date for this phase. Depending
   * on the M-Target, M-Approved, or M-Launched values, this date means
   * different things.
   * @return {number} Unix timestamp in seconds.
   * @private
   */
  get _nextDate() {
    const phaseName = this.phaseName;
    const status = this._status;
    let data = this._milestoneData && this._milestoneData.mstones;
    // Data pulled from https://chromiumdash.appspot.com/fetch_milestone_schedule?mstone=xx
    if (!phaseName || !status || !data || !data.length) return 0;
    data = data[0];

    let key = TARGET_PHASE_MILESTONE_MAP[phaseName];
    if (['Approved', 'Launched'].includes(status)) {
      const osValues = this._fieldValueMap.get('OS');
      // If iOS is the only OS and the phase is one where iOS has unique
      // milestones, the only date we show should be this._nextUniqueiOSDate.
      if (osValues && osValues.every((os) => {
        return os === 'iOS';
      }) && phaseName in IOS_APPROVED_PHASE_MILESTONE_MAP) {
        return 0;
      }
      key = APPROVED_PHASE_MILESTONE_MAP[phaseName];
    }
    if (!key || !(key in data)) return 0;
    return Math.floor((new Date(data[key])).getTime() / 1000);
  }

  /**
   * For issues where iOS is the OS, this function finds the relevant iOS
   * launch date.
   * @return {number} Unix timestamp in seconds.
   * @private
   */
  get _nextUniqueiOSDate() {
    const phaseName = this.phaseName;
    const status = this._status;
    let data = this._milestoneData && this._milestoneData.mstones;
    // Data pull from https://chromiumdash.appspot.com/fetch_milestone_schedule?mstone=xx
    if (!phaseName || !status || !data || !data.length) return 0;
    data = data[0];

    const osValues = this._fieldValueMap.get('OS');
    if (['Approved', 'Launched'].includes(status) &&
        osValues && osValues.includes('iOS')) {
      const key = IOS_APPROVED_PHASE_MILESTONE_MAP[phaseName];
      if (key) {
        return Math.floor((new Date(data[key])).getTime() / 1000);
      }
    }
    return 0;
  }

  /**
   * Depending on what kind of date we're showing, we want to include
   * different text to describe the date.
   * @return {string}
   * @private
   */
  get _dateDescriptor() {
    const status = this._status;
    if (status === 'Approved') {
      return 'Launching on ';
    } else if (status === 'Launched') {
      return 'Launched on ';
    }
    return 'Due by ';
  }

  /**
   * The Chrome-specific status of a gate, computed from M-Approved,
   * M-Launched, and M-Target fields.
   * @return {string}
   * @private
   */
  get _status() {
    const target = this._targetMilestone;
    const approved = this._approvedMilestone;
    const launched = this._launchedMilestone;
    if (approved >= target) {
      if (launched >= approved) {
        return 'Launched';
      }
      return 'Approved';
    }
    return 'Target';
  }

  /**
   * The Chrome Milestone that this phase was approved for.
   * @return {string}
   * @private
   */
  get _approvedMilestone() {
    return valueForField(this._fieldValueMap, 'M-Approved', this.phaseName);
  }

  /**
   * The Chrome Milestone that this phase was launched on.
   * @return {string}
   * @private
   */
  get _launchedMilestone() {
    return valueForField(this._fieldValueMap, 'M-Launched', this.phaseName);
  }

  /**
   * The Chrome Milestone that this phase is targeting.
   * @return {string}
   * @private
   */
  get _targetMilestone() {
    return valueForField(this._fieldValueMap, 'M-Target', this.phaseName);
  }

  /**
   * The Chrome Milestone that's used to decide what date to show the user.
   * @return {string}
   * @private
   */
  get _milestoneToFetch() {
    const target = Number.parseInt(this._targetMilestone) || 0;
    const approved = Number.parseInt(this._approvedMilestone) || 0;
    const launched = Number.parseInt(this._launchedMilestone) || 0;

    const latestMilestone = Math.max(target, approved, launched);
    return latestMilestone > 0 ? `${latestMilestone}` : '';
  }
}


customElements.define('mr-phase', MrPhase);
