// 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 deepEqual from 'deep-equal';

import 'elements/chops/chops-button/chops-button.js';
import 'elements/framework/mr-upload/mr-upload.js';
import 'elements/framework/mr-star/mr-issue-star.js';
import 'elements/chops/chops-checkbox/chops-checkbox.js';
import 'elements/chops/chops-chip/chops-chip.js';
import 'elements/framework/mr-error/mr-error.js';
import 'elements/framework/mr-warning/mr-warning.js';
import 'elements/help/mr-cue/mr-cue.js';
import 'react/mr-react-autocomplete.tsx';
import {cueNames} from 'elements/help/mr-cue/cue-helpers.js';
import {store, connectStore} from 'reducers/base.js';
import {UserInputError} from 'shared/errors.js';
import {fieldTypes} from 'shared/issue-fields.js';
import {displayNameToUserRef, labelStringToRef, componentStringToRef,
  componentRefsToStrings, issueStringToRef, issueStringToBlockingRef,
  issueRefToString, issueRefsToStrings, filteredUserDisplayNames,
  valueToFieldValue, fieldDefToName,
} from 'shared/convertersV0.js';
import {arrayDifference, isEmptyObject, equalsIgnoreCase} from 'shared/helpers.js';
import {NON_EDITING_KEY_EVENTS} from 'shared/dom-helpers.js';
import * as issueV0 from 'reducers/issueV0.js';
import * as permissions from 'reducers/permissions.js';
import * as projectV0 from 'reducers/projectV0.js';
import * as userV0 from 'reducers/userV0.js';
import * as ui from 'reducers/ui.js';
import '../mr-edit-field/mr-edit-field.js';
import '../mr-edit-field/mr-edit-status.js';
import {ISSUE_EDIT_PERMISSION, ISSUE_EDIT_SUMMARY_PERMISSION,
  ISSUE_EDIT_STATUS_PERMISSION, ISSUE_EDIT_OWNER_PERMISSION,
  ISSUE_EDIT_CC_PERMISSION,
} from 'shared/consts/permissions.js';
import {fieldDefsWithGroup, fieldDefsWithoutGroup, valuesForField,
  HARDCODED_FIELD_GROUPS} from 'shared/metadata-helpers.js';
import {renderMarkdown, shouldRenderMarkdown} from 'shared/md-helper.js';
import {unsafeHTML} from 'lit-html/directives/unsafe-html.js';
import {MD_PREVIEW_STYLES, MD_STYLES} from 'shared/shared-styles.js';



/**
 * `<mr-edit-metadata>`
 *
 * Editing form for either an approval or the overall issue.
 *
 */
export class MrEditMetadata extends connectStore(LitElement) {
  /** @override */
  render() {
    return html`
      <style>
        ${MD_PREVIEW_STYLES}
        ${MD_STYLES}
        mr-edit-metadata {
          display: block;
          font-size: var(--chops-main-font-size);
        }
        mr-edit-metadata[hidden] {
          display: none;
        }
        mr-edit-metadata.edit-actions-right .edit-actions {
          flex-direction: row-reverse;
          text-align: right;
        }
        mr-edit-metadata.edit-actions-right .edit-actions chops-checkbox {
          text-align: left;
        }
        .edit-actions chops-checkbox {
          max-width: 200px;
          margin-top: 2px;
          flex-grow: 2;
          text-align: right;
        }
        .edit-actions {
          width: 100%;
          max-width: 500px;
          margin: 0.5em 0;
          text-align: left;
          display: flex;
          flex-direction: row;
          align-items: center;
        }
        .edit-actions chops-button {
          flex-grow: 0;
          flex-shrink: 0;
        }
        .edit-actions .emphasized {
          margin-left: 0;
        }
        input {
          box-sizing: border-box;
          width: var(--mr-edit-field-width);
          padding: var(--mr-edit-field-padding);
          font-size: var(--chops-main-font-size);
        }
        mr-upload {
          margin-bottom: 0.25em;
        }
        textarea {
          font-family: var(--mr-toggled-font-family);
          width: 100%;
          margin: 0.25em 0;
          box-sizing: border-box;
          border: var(--chops-accessible-border);
          height: 8em;
          transition: height 0.1s ease-in-out;
          padding: 0.5em 4px;
          grid-column-start: 1;
          grid-column-end: 2;
        }
        button.toggle {
          background: none;
          color: var(--chops-link-color);
          border: 0;
          width: 100%;
          padding: 0.25em 0;
          text-align: left;
        }
        button.toggle:hover {
          cursor: pointer;
          text-decoration: underline;
        }
        .presubmit-derived {
          color: gray;
          font-style: italic;
          text-decoration-line: underline;
          text-decoration-style: dotted;
        }
        .presubmit-derived-header {
          color: gray;
          font-weight: bold;
        }
        .discard-button {
          margin-right: 16px;
          margin-left: 16px;
        }
        .group {
          width: 100%;
          border: 1px solid hsl(0, 0%, 83%);
          grid-column: 1 / -1;
          margin: 0;
          margin-bottom: 0.5em;
          padding: 0;
          padding-bottom: 0.5em;
        }
        .group legend {
          margin-left: 130px;
        }
        .group-title {
          text-align: center;
          font-style: oblique;
          margin-top: 4px;
          margin-bottom: -8px;
        }
        .star-line {
          display: flex;
          align-items: center;
          background: var(--chops-notice-bubble-bg);
          border: var(--chops-notice-border);
          justify-content: flex-start;
          margin-top: 4px;
          padding: 2px 4px 2px 8px;
        }
        mr-issue-star {
          margin-right: 4px;
        }
      </style>
      <link href="https://fonts.googleapis.com/icon?family=Material+Icons"
            rel="stylesheet">
      <form id="editForm"
        @submit=${this._save}
        @keydown=${this._saveOnCtrlEnter}
      >
        <mr-cue cuePrefName=${cueNames.CODE_OF_CONDUCT}></mr-cue>
        ${this._renderStarLine()}
        <textarea
          id="commentText"
          placeholder="Add a comment"
          @keyup=${this._processChanges}
          aria-label="Comment"
        ></textarea>
        ${(this._renderMarkdown)
           ? html`
          <div class="markdown-preview preview-height-comment">
            <div class="markdown">
              ${unsafeHTML(renderMarkdown(this.getCommentContent()))}
            </div>
          </div>`: ''}
        <mr-upload
          ?hidden=${this.disableAttachments}
          @change=${this._processChanges}
        ></mr-upload>
        <div class="input-grid">
          ${this._renderEditFields()}
          ${this._renderErrorsAndWarnings()}

          <span></span>
          <div class="edit-actions">
            <chops-button
              @click=${this._save}
              class="save-changes emphasized"
              ?disabled=${this.disabled}
              title="Save changes (Ctrl+Enter / \u2318+Enter)"
            >
              Save changes
            </chops-button>
            <chops-button
              @click=${this.discard}
              class="de-emphasized discard-button"
              ?disabled=${this.disabled}
            >
              Discard
            </chops-button>

            <chops-checkbox
              id="sendEmail"
              @checked-change=${this._sendEmailChecked}
              ?checked=${this.sendEmail}
            >Send email</chops-checkbox>
          </div>

          ${!this.isApproval ? this._renderPresubmitChanges() : ''}
        </div>
      </form>
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderStarLine() {
    if (this._canEditIssue || this.isApproval) return '';

    return html`
      <div class="star-line">
        <mr-issue-star
          .issueRef=${this.issueRef}
        ></mr-issue-star>
        <span>
          ${this.isStarred ? `
            You have voted for this issue and will receive notifications.
          ` : `
            Star this issue instead of commenting "+1 Me too!" to add a vote
            and get notifications.`}
        </span>
      </div>
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderPresubmitChanges() {
    const {derivedCcs, derivedLabels} = this.presubmitResponse || {};
    const hasCcs = derivedCcs && derivedCcs.length;
    const hasLabels = derivedLabels && derivedLabels.length;
    const hasDerivedValues = hasCcs || hasLabels;
    return html`
      ${hasDerivedValues ? html`
        <span></span>
        <div class="presubmit-derived-header">
          Filter rules and components will add
        </div>
        ` : ''}

      ${hasCcs? html`
        <label
          for="derived-ccs"
          class="presubmit-derived-header"
        >CC:</label>
        <div id="derived-ccs">
          ${derivedCcs.map((cc) => html`
            <span
              title=${cc.why}
              class="presubmit-derived"
            >${cc.value}</span>
          `)}
        </div>
        ` : ''}

      ${hasLabels ? html`
        <label
          for="derived-labels"
          class="presubmit-derived-header"
        >Labels:</label>
        <div id="derived-labels">
          ${derivedLabels.map((label) => html`
            <span
              title=${label.why}
              class="presubmit-derived"
            >${label.value}</span>
          `)}
        </div>
        ` : ''}
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderErrorsAndWarnings() {
    const presubmitResponse = this.presubmitResponse || {};
    const presubmitWarnings = presubmitResponse.warnings || [];
    const presubmitErrors = presubmitResponse.errors || [];
    return (this.error || presubmitWarnings.length || presubmitErrors.length) ?
      html`
        <span></span>
        <div>
          ${presubmitWarnings.map((warning) => html`
            <mr-warning title=${warning.why}>${warning.value}</mr-warning>
          `)}
          <!-- TODO(ehmaldonado): Look into blocking submission on presubmit
          -->
          ${presubmitErrors.map((error) => html`
            <mr-error title=${error.why}>${error.value}</mr-error>
          `)}
          ${this.error ? html`
            <mr-error>${this.error}</mr-error>` : ''}
        </div>
      ` : '';
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderEditFields() {
    if (this.isApproval) {
      return html`
        ${this._renderStatus()}
        ${this._renderApprovers()}
        ${this._renderFieldDefs()}

        ${this._renderNicheFieldToggle()}
      `;
    }

    return html`
      ${this._canEditSummary ? this._renderSummary() : ''}
      ${this._canEditStatus ? this._renderStatus() : ''}
      ${this._canEditOwner ? this._renderOwner() : ''}
      ${this._canEditCC ? this._renderCC() : ''}
      ${this._canEditIssue ? html`
        ${this._renderComponents()}

        ${this._renderFieldDefs()}
        ${this._renderRelatedIssues()}
        ${this._renderLabels()}

        ${this._renderNicheFieldToggle()}
      ` : ''}
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderSummary() {
    return html`
      <label for="summaryInput">Summary:</label>
      <input
        id="summaryInput"
        value=${this.summary}
        @keyup=${this._processChanges}
      />
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderOwner() {
    const ownerPresubmit = this._ownerPresubmit;
    return html`
      <label for="ownerInput">
        ${ownerPresubmit.message ? html`
          <i
            class=${`material-icons inline-${ownerPresubmit.icon}`}
            title=${ownerPresubmit.message}
          >${ownerPresubmit.icon}</i>
        ` : ''}
        Owner:
      </label>
      <mr-react-autocomplete
        label="ownerInput"
        vocabularyName="owner"
        .placeholder=${ownerPresubmit.placeholder}
        .value=${this._values.owner}
        .onChange=${this._changeHandlers.owner}
      ></mr-react-autocomplete>
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderCC() {
    return html`
      <label for="ccInput">CC:</label>
      <mr-react-autocomplete
        label="ccInput"
        vocabularyName="member"
        .multiple=${true}
        .fixedValues=${this._derivedCCs}
        .value=${this._values.cc}
        .onChange=${this._changeHandlers.cc}
      ></mr-react-autocomplete>
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderComponents() {
    return html`
      <label for="componentsInput">Components:</label>
      <mr-react-autocomplete
        label="componentsInput"
        vocabularyName="component"
        .multiple=${true}
        .value=${this._values.components}
        .onChange=${this._changeHandlers.components}
      ></mr-react-autocomplete>
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderApprovers() {
    return this.hasApproverPrivileges && this.isApproval ? html`
      <label for="approversInput_react">Approvers:</label>
      <mr-edit-field
        id="approversInput"
        label="approversInput_react"
        .type=${'USER_TYPE'}
        .initialValues=${filteredUserDisplayNames(this.approvers)}
        .name=${'approver'}
        .acType=${'member'}
        @change=${this._processChanges}
        multi
      ></mr-edit-field>
    ` : '';
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderStatus() {
    return this.statuses && this.statuses.length ? html`
      <label for="statusInput">Status:</label>

      <mr-edit-status
        id="statusInput"
        .initialStatus=${this.status}
        .statuses=${this.statuses}
        .mergedInto=${issueRefToString(this.mergedInto, this.projectName)}
        ?isApproval=${this.isApproval}
        @change=${this._processChanges}
      ></mr-edit-status>
    ` : '';
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderFieldDefs() {
    return html`
      ${fieldDefsWithGroup(this.fieldDefs, this.fieldGroups, this.issueType).map((group) => html`
        <fieldset class="group">
          <legend>${group.groupName}</legend>
          <div class="input-grid">
            ${group.fieldDefs.map((field) => this._renderCustomField(field))}
          </div>
        </fieldset>
      `)}

      ${fieldDefsWithoutGroup(this.fieldDefs, this.fieldGroups, this.issueType).map((field) => this._renderCustomField(field))}
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderRelatedIssues() {
    return html`
      <label for="blockedOnInput">BlockedOn:</label>
      <mr-react-autocomplete
        label="blockedOnInput"
        vocabularyName="component"
        .multiple=${true}
        .value=${this._values.blockedOn}
        .onChange=${this._changeHandlers.blockedOn}
      ></mr-react-autocomplete>

      <label for="blockingInput">Blocking:</label>
      <mr-react-autocomplete
        label="blockingInput"
        vocabularyName="component"
        .multiple=${true}
        .value=${this._values.blocking}
        .onChange=${this._changeHandlers.blocking}
      ></mr-react-autocomplete>
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderLabels() {
    return html`
      <label for="labelsInput">Labels:</label>
      <mr-react-autocomplete
        label="labelsInput"
        vocabularyName="label"
        .multiple=${true}
        .fixedValues=${this.derivedLabels}
        .value=${this._values.labels}
        .onChange=${this._changeHandlers.labels}
      ></mr-react-autocomplete>
    `;
  }

  /**
   * @return {TemplateResult}
   * @param {FieldDef} field The custom field beinf rendered.
   * @private
   */
  _renderCustomField(field) {
    if (!field || !field.fieldRef) return '';
    const userCanEdit = this._userCanEdit(field);
    const {fieldRef, isNiche, docstring, isMultivalued} = field;
    const isHidden = (!this.showNicheFields && isNiche) || !userCanEdit;

    let acType;
    if (fieldRef.type === fieldTypes.USER_TYPE) {
      acType = isMultivalued ? 'member' : 'owner';
    }
    return html`
      <label
        ?hidden=${isHidden}
        for=${this._idForField(fieldRef.fieldName) + '_react'}
        title=${docstring}
      >
        ${fieldRef.fieldName}:
      </label>
      <mr-edit-field
        ?hidden=${isHidden}
        id=${this._idForField(fieldRef.fieldName)}
        .label=${this._idForField(fieldRef.fieldName) + '_react'}
        .name=${fieldRef.fieldName}
        .type=${fieldRef.type}
        .options=${this._optionsForField(this.optionsPerEnumField, this.fieldValueMap, fieldRef.fieldName, this.phaseName)}
        .initialValues=${valuesForField(this.fieldValueMap, fieldRef.fieldName, this.phaseName)}
        .acType=${acType}
        ?multi=${isMultivalued}
        @change=${this._processChanges}
      ></mr-edit-field>
    `;
  }

  /**
   * @return {TemplateResult}
   * @private
   */
  _renderNicheFieldToggle() {
    return this._nicheFieldCount ? html`
      <span></span>
      <button type="button" class="toggle" @click=${this.toggleNicheFields}>
        <span ?hidden=${this.showNicheFields}>
          Show all fields (${this._nicheFieldCount} currently hidden)
        </span>
        <span ?hidden=${!this.showNicheFields}>
          Hide niche fields (${this._nicheFieldCount} currently shown)
        </span>
      </button>
    ` : '';
  }

  /** @override */
  static get properties() {
    return {
      fieldDefs: {type: Array},
      formName: {type: String},
      approvers: {type: Array},
      setter: {type: Object},
      summary: {type: String},
      cc: {type: Array, hasChanged: _notDeepEqual},
      components: {type: Array, hasChanged: _notDeepEqual},
      status: {type: String},
      statuses: {type: Array},
      blockedOn: {type: Array, hasChanged: _notDeepEqual},
      blocking: {type: Array, hasChanged: _notDeepEqual},
      mergedInto: {type: Object},
      ownerName: {type: String, hasChanged: _notDeepEqual},
      labelNames: {type: Array, hasChanged: _notDeepEqual},
      derivedLabels: {type: Array},
      _permissions: {type: Array},
      phaseName: {type: String},
      projectConfig: {type: Object},
      projectName: {type: String, hasChanged: _notDeepEqual},
      isApproval: {type: Boolean},
      isStarred: {type: Boolean},
      issuePermissions: {type: Object},
      issueRef: {type: Object},
      hasApproverPrivileges: {type: Boolean},
      showNicheFields: {type: Boolean},
      disableAttachments: {type: Boolean},
      error: {type: String},
      sendEmail: {type: Boolean},
      presubmitResponse: {type: Object},
      fieldValueMap: {type: Object},
      issueType: {type: String},
      optionsPerEnumField: {type: String},
      fieldGroups: {type: Object},
      prefs: {type: Object},
      saving: {type: Boolean},
      isDirty: {type: Boolean},
      _values: {type: Object},
      _initialValues: {type: Object},
    };
  }

  /** @override */
  constructor() {
    super();
    this.summary = '';
    this.ownerName = '';
    this.sendEmail = true;
    this.mergedInto = {};
    this.issueRef = {};
    this.fieldGroups = HARDCODED_FIELD_GROUPS;

    this._permissions = {};
    this.saving = false;
    this.isDirty = false;
    this.prefs = {};
    this._values = {};
    this._initialValues = {};

    // Memoize change handlers so property updates don't cause excess rerenders.
    this._changeHandlers = {
      owner: this._onChange.bind(this, 'owner'),
      cc: this._onChange.bind(this, 'cc'),
      components: this._onChange.bind(this, 'components'),
      labels: this._onChange.bind(this, 'labels'),
      blockedOn: this._onChange.bind(this, 'blockedOn'),
      blocking: this._onChange.bind(this, 'blocking'),
    };
  }

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

  /** @override */
  firstUpdated() {
    this.hasRendered = true;
  }

  /** @override */
  updated(changedProperties) {
    if (changedProperties.has('ownerName') || changedProperties.has('cc')
        || changedProperties.has('components')
        || changedProperties.has('labelNames')
        || changedProperties.has('blockedOn')
        || changedProperties.has('blocking')
        || changedProperties.has('projectName')) {
      this._initialValues.owner = this.ownerName;
      this._initialValues.cc = this._ccNames;
      this._initialValues.components = componentRefsToStrings(this.components);
      this._initialValues.labels = this.labelNames;
      this._initialValues.blockedOn = issueRefsToStrings(this.blockedOn, this.projectName);
      this._initialValues.blocking = issueRefsToStrings(this.blocking, this.projectName);

      this._values = {...this._initialValues};
    }
  }

  /**
   * Getter for checking if the user has Markdown enabled.
   * @return {boolean} Whether Markdown preview should be rendered or not.
   */
  get _renderMarkdown() {
    if (!this.getCommentContent()) {
      return false;
    }
    const enabled = this.prefs.get('render_markdown');
    return shouldRenderMarkdown({project: this.projectName, enabled});
  }

  /**
   * @return {boolean} Whether the "Save changes" button is disabled.
   */
  get disabled() {
    return !this.isDirty || this.saving;
  }

  /**
   * Set isDirty to a property instead of only using a getter to cause
   * lit-element to re-render when dirty state change.
   */
  _updateIsDirty() {
    if (!this.hasRendered) return;

    const commentContent = this.getCommentContent();
    const attachmentsElement = this.querySelector('mr-upload');
    this.isDirty = !isEmptyObject(this.delta) || Boolean(commentContent) ||
      attachmentsElement.hasAttachments;
  }

  get _nicheFieldCount() {
    const fieldDefs = this.fieldDefs || [];
    return fieldDefs.reduce((acc, fd) => acc + (fd.isNiche | 0), 0);
  }

  get _canEditIssue() {
    const issuePermissions = this.issuePermissions || [];
    return issuePermissions.includes(ISSUE_EDIT_PERMISSION);
  }

  get _canEditSummary() {
    const issuePermissions = this.issuePermissions || [];
    return this._canEditIssue ||
      issuePermissions.includes(ISSUE_EDIT_SUMMARY_PERMISSION);
  }

  get _canEditStatus() {
    const issuePermissions = this.issuePermissions || [];
    return this._canEditIssue ||
      issuePermissions.includes(ISSUE_EDIT_STATUS_PERMISSION);
  }

  get _canEditOwner() {
    const issuePermissions = this.issuePermissions || [];
    return this._canEditIssue ||
      issuePermissions.includes(ISSUE_EDIT_OWNER_PERMISSION);
  }

  get _canEditCC() {
    const issuePermissions = this.issuePermissions || [];
    return this._canEditIssue ||
      issuePermissions.includes(ISSUE_EDIT_CC_PERMISSION);
  }

  /**
   * @return {Array<string>}
   */
  get _ccNames() {
    const users = this.cc || [];
    return filteredUserDisplayNames(users.filter((u) => !u.isDerived));
  }

  get _derivedCCs() {
    const users = this.cc || [];
    return filteredUserDisplayNames(users.filter((u) => u.isDerived));
  }

  get _ownerPresubmit() {
    const response = this.presubmitResponse;
    if (!response) return {};

    const ownerView = {message: '', placeholder: '', icon: ''};

    if (response.ownerAvailability) {
      ownerView.message = response.ownerAvailability;
      ownerView.icon = 'warning';
    } else if (response.derivedOwners && response.derivedOwners.length) {
      ownerView.placeholder = response.derivedOwners[0].value;
      ownerView.message = response.derivedOwners[0].why;
      ownerView.icon = 'info';
    }
    return ownerView;
  }

  /** @override */
  stateChanged(state) {
    this.fieldValueMap = issueV0.fieldValueMap(state);
    this.issueType = issueV0.type(state);
    this.issueRef = issueV0.viewedIssueRef(state);
    this._permissions = permissions.byName(state);
    this.presubmitResponse = issueV0.presubmitResponse(state);
    this.projectConfig = projectV0.viewedConfig(state);
    this.projectName = issueV0.viewedIssueRef(state).projectName;
    this.issuePermissions = issueV0.permissions(state);
    this.optionsPerEnumField = projectV0.optionsPerEnumField(state);
    // Access boolean value from allStarredIssues
    const starredIssues = issueV0.starredIssues(state);
    this.isStarred = starredIssues.has(issueRefToString(this.issueRef));
    this.prefs = userV0.prefs(state);
  }

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

    store.dispatch(ui.reportDirtyForm(this.formName, false));
  }

  /**
   * Resets the edit form values to their default values.
   */
  async reset() {
    this._values = {...this._initialValues};

    const form = this.querySelector('#editForm');
    if (!form) return;

    form.reset();
    const statusInput = this.querySelector('#statusInput');
    if (statusInput) {
      statusInput.reset();
    }

    // Since custom elements containing <input> elements have the inputs
    // wrapped in ShadowDOM, those inputs don't get reset with the rest of
    // the form. Haven't been able to figure out a way to replicate form reset
    // behavior with custom input elements.
    if (this.isApproval) {
      if (this.hasApproverPrivileges) {
        const approversInput = this.querySelector(
            '#approversInput');
        if (approversInput) {
          approversInput.reset();
        }
      }
    }
    this.querySelectorAll('mr-edit-field').forEach((el) => {
      el.reset();
    });

    const uploader = this.querySelector('mr-upload');
    if (uploader) {
      uploader.reset();
    }

    // TODO(dtu, zhangtiff): Remove once all form fields are controlled.
    await this.updateComplete;

    this._processChanges();
  }

  /**
   * @param {MouseEvent|SubmitEvent} event
   * @private
   */
  _save(event) {
    event.preventDefault();
    this.save();
  }

  /**
   * Users may use either Ctrl+Enter or Command+Enter to save an issue edit
   * while the issue edit form is focused.
   * @param {KeyboardEvent} event
   * @private
   */
  _saveOnCtrlEnter(event) {
    if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
      event.preventDefault();
      this.save();
    }
  }

  /**
   * Tells the parent to save the current edited values in the form.
   * @fires CustomEvent#save
   */
  save() {
    this.dispatchEvent(new CustomEvent('save'));
  }

  /**
   * Tells the parent component that the user is trying to discard the form,
   * if they confirm that that's what they're doing. The parent decides what
   * to do in order to quit the editing session.
   * @fires CustomEvent#discard
   */
  discard() {
    const isDirty = this.isDirty;
    if (!isDirty || confirm('Discard your changes?')) {
      this.dispatchEvent(new CustomEvent('discard'));
    }
  }

  /**
   * Focuses the comment form.
   */
  async focus() {
    await this.updateComplete;
    this.querySelector('#commentText').focus();
  }

  /**
   * Retrieves the value of the comment that the user added from the DOM.
   * @return {string}
   */
  getCommentContent() {
    if (!this.querySelector('#commentText')) {
      return '';
    }
    return this.querySelector('#commentText').value;
  }

  async getAttachments() {
    try {
      return await this.querySelector('mr-upload').loadFiles();
    } catch (e) {
      this.error = `Error while loading file for attachment: ${e.message}`;
    }
  }

  /**
   * @param {FieldDef} field
   * @return {boolean}
   * @private
   */
  _userCanEdit(field) {
    const fieldName = fieldDefToName(this.projectName, field);
    if (!this._permissions[fieldName] ||
        !this._permissions[fieldName].permissions) return false;
    const userPerms = this._permissions[fieldName].permissions;
    return userPerms.includes(permissions.FIELD_DEF_VALUE_EDIT);
  }

  /**
   * Shows or hides custom fields with the "isNiche" attribute set to true.
   */
  toggleNicheFields() {
    this.showNicheFields = !this.showNicheFields;
  }

  /**
   * @return {IssueDelta}
   * @throws {UserInputError}
   */
  get delta() {
    try {
      this.error = '';
      return this._getDelta();
    } catch (e) {
      if (!(e instanceof UserInputError)) throw e;
      this.error = e.message;
      return {};
    }
  }

  /**
   * Generates a change between the initial Issue state and what the user
   * inputted.
   * @return {IssueDelta}
   */
  _getDelta() {
    let result = {};

    const {projectName, localId} = this.issueRef;

    const statusInput = this.querySelector('#statusInput');
    if (this._canEditStatus && statusInput) {
      const statusDelta = statusInput.delta;
      if (statusDelta.mergedInto) {
        result.mergedIntoRef = issueStringToBlockingRef(
            {projectName, localId}, statusDelta.mergedInto);
      }
      if (statusDelta.status) {
        result.status = statusDelta.status;
      }
    }

    if (this.isApproval) {
      if (this._canEditIssue && this.hasApproverPrivileges) {
        result = {
          ...result,
          ...this._changedValuesDom(
            'approvers', 'approverRefs', displayNameToUserRef),
        };
      }
    } else {
      // TODO(zhangtiff): Consider representing baked-in fields such as owner,
      // cc, and status similarly to custom fields to reduce repeated code.

      if (this._canEditSummary) {
        const summaryInput = this.querySelector('#summaryInput');
        if (summaryInput) {
          const newSummary = summaryInput.value;
          if (newSummary !== this.summary) {
            result.summary = newSummary;
          }
        }
      }

      if (this._values.owner !== this._initialValues.owner) {
        result.ownerRef = displayNameToUserRef(this._values.owner);
      }

      const blockerAddFn = (refString) =>
        issueStringToBlockingRef({projectName, localId}, refString);
      const blockerRemoveFn = (refString) =>
        issueStringToRef(refString, projectName);

      result = {
        ...result,
        ...this._changedValuesControlled(
          'cc', 'ccRefs', displayNameToUserRef),
        ...this._changedValuesControlled(
          'components', 'compRefs', componentStringToRef),
        ...this._changedValuesControlled(
          'labels', 'labelRefs', labelStringToRef),
        ...this._changedValuesControlled(
          'blockedOn', 'blockedOnRefs', blockerAddFn, blockerRemoveFn),
        ...this._changedValuesControlled(
          'blocking', 'blockingRefs', blockerAddFn, blockerRemoveFn),
      };
    }

    if (this._canEditIssue) {
      const fieldDefs = this.fieldDefs || [];
      fieldDefs.forEach(({fieldRef}) => {
        const {fieldValsAdd = [], fieldValsRemove = []} =
          this._changedValuesDom(fieldRef.fieldName, 'fieldVals',
            valueToFieldValue.bind(null, fieldRef));

        // Because multiple custom fields share the same "fieldVals" key in
        // delta, we hav to make sure to concatenate updated delta values with
        // old delta values.
        if (fieldValsAdd.length) {
          result.fieldValsAdd = [...(result.fieldValsAdd || []),
            ...fieldValsAdd];
        }

        if (fieldValsRemove.length) {
          result.fieldValsRemove = [...(result.fieldValsRemove || []),
            ...fieldValsRemove];
        }
      });
    }

    return result;
  }

  /**
   * Computes delta values for a controlled input.
   * @param {string} fieldName The key in the values property to retrieve data.
   *   from.
   * @param {string} responseKey The key in the delta Object that changes will be
   *   saved in.
   * @param {function(string): any} addFn A function to specify how to format
   *   the message for a given added field.
   * @param {function(string): any} removeFn A function to specify how to format
   *   the message for a given removed field.
   * @return {Object} delta fragment for added and removed values.
   */
  _changedValuesControlled(fieldName, responseKey, addFn, removeFn) {
    const values = this._values[fieldName];
    const initialValues = this._initialValues[fieldName];

    const valuesAdd = arrayDifference(values, initialValues, equalsIgnoreCase);
    const valuesRemove =
      arrayDifference(initialValues, values, equalsIgnoreCase);

    return this._changedValues(valuesAdd, valuesRemove, responseKey, addFn, removeFn);
  }

  /**
   * Gets changes values when reading from a legacy <mr-edit-field> element.
   * @param {string} fieldName Name of the form input we're checking values on.
   * @param {string} responseKey The key in the delta Object that changes will be
   *   saved in.
   * @param {function(string): any} addFn A function to specify how to format
   *   the message for a given added field.
   * @param {function(string): any} removeFn A function to specify how to format
   *   the message for a given removed field.
   * @return {Object} delta fragment for added and removed values.
   */
  _changedValuesDom(fieldName, responseKey, addFn, removeFn) {
    const input = this.querySelector(`#${this._idForField(fieldName)}`);
    if (!input) return;

    const valuesAdd = input.getValuesAdded();
    const valuesRemove = input.getValuesRemoved();

    return this._changedValues(valuesAdd, valuesRemove, responseKey, addFn, removeFn);
  }

  /**
   * Shared helper function for computing added and removed values for a
   * single field in a delta.
   * @param {Array<string>} valuesAdd The added values. For example, new CCed
   *   users.
   * @param {Array<string>} valuesRemove Values that were removed in this edit.
   * @param {string} responseKey The key in the delta Object that changes will be
   *   saved in.
   * @param {function(string): any} addFn A function to specify how to format
   *   the message for a given added field.
   * @param {function(string): any} removeFn A function to specify how to format
   *   the message for a given removed field.
   * @return {Object} delta fragment for added and removed values.
   */
  _changedValues(valuesAdd, valuesRemove, responseKey, addFn, removeFn) {
    const delta = {};

    if (valuesAdd && valuesAdd.length) {
      delta[responseKey + 'Add'] = valuesAdd.map(addFn);
    }

    if (valuesRemove && valuesRemove.length) {
      delta[responseKey + 'Remove'] = valuesRemove.map(removeFn || addFn);
    }

    return delta;
  }

  /**
   * Generic onChange handler to be bound to each form field.
   * @param {string} key Unique name for the form field we're binding this
   *   handler to. For example, 'owner', 'cc', or the name of a custom field.
   * @param {Event} event
   * @param {string|Array<string>} value The new form value.
   * @param {*} _reason
   */
  _onChange(key, event, value, _reason) {
    this._values = {...this._values, [key]: value};
    this._processChanges(event);
  }

  /**
   * Event handler for running filter rules presubmit logic.
   * @param {Event} e
   */
  _processChanges(e) {
    if (e instanceof KeyboardEvent) {
      if (NON_EDITING_KEY_EVENTS.has(e.key)) return;
    }
    this._updateIsDirty();

    store.dispatch(ui.reportDirtyForm(this.formName, this.isDirty));

    this.dispatchEvent(new CustomEvent('change', {
      detail: {
        delta: this.delta,
        commentContent: this.getCommentContent(),
      },
    }));
  }

  _idForField(name) {
    return `${name}Input`;
  }

  _optionsForField(optionsPerEnumField, fieldValueMap, fieldName, phaseName) {
    if (!optionsPerEnumField || !fieldName) return [];
    const key = fieldName.toLowerCase();
    if (!optionsPerEnumField.has(key)) return [];
    const options = [...optionsPerEnumField.get(key)];
    const values = valuesForField(fieldValueMap, fieldName, phaseName);
    values.forEach((v) => {
      const optionExists = options.find(
          (opt) => equalsIgnoreCase(opt.optionName, v));
      if (!optionExists) {
        // Note that enum fields which are not explicitly defined can be set,
        // such as in the case when an issue is moved.
        options.push({optionName: v});
      }
    });
    return options;
  }

  _sendEmailChecked(evt) {
    this.sendEmail = evt.detail.checked;
  }
}

function _notDeepEqual(a, b) {
  return !deepEqual(a, b);
}

customElements.define('mr-edit-metadata', MrEditMetadata);
