/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../../styles/shared-styles';
import '../../../styles/gr-font-styles';
import '../../../styles/gr-change-metadata-shared-styles';
import '../../../styles/gr-change-view-integration-shared-styles';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import '../../plugins/gr-endpoint-param/gr-endpoint-param';
import '../../shared/gr-account-chip/gr-account-chip';
import '../../shared/gr-date-formatter/gr-date-formatter';
import '../../shared/gr-editable-label/gr-editable-label';
import '../../shared/gr-icon/gr-icon';
import '../../shared/gr-limited-text/gr-limited-text';
import '../../shared/gr-linked-chip/gr-linked-chip';
import '../../shared/gr-tooltip-content/gr-tooltip-content';
import '../../shared/gr-weblink/gr-weblink';
import '../gr-submit-requirements/gr-submit-requirements';
import '../gr-commit-info/gr-commit-info';
import '../gr-reviewer-list/gr-reviewer-list';
import {
  ChangeStatus,
  GpgKeyInfoStatus,
  InheritedBooleanInfoConfiguredValue,
  SubmitType,
} from '../../../constants/constants';
import {changeIsOpen, isOwner} from '../../../utils/change-util';
import {
  AccountDetailInfo,
  AccountInfo,
  ApprovalInfo,
  BranchName,
  ChangeInfo,
  CommitId,
  CommitInfo,
  ConfigInfo,
  GpgKeyInfo,
  Hashtag,
  isAccount,
  isDetailedLabelInfo,
  LabelInfo,
  LabelNameToInfoMap,
  NumericChangeId,
  ParentCommitInfo,
  RevisionPatchSetNum,
  RepoName,
  RevisionInfo,
  ServerInfo,
  WebLinkInfo,
} from '../../../types/common';
import {assertIsDefined, assertNever, unique} from '../../../utils/common-util';
import {GrEditableLabel} from '../../shared/gr-editable-label/gr-editable-label';
import {GrLinkedChip} from '../../shared/gr-linked-chip/gr-linked-chip';
import {getAppContext} from '../../../services/app-context';
import {
  Metadata,
  isSectionSet,
  DisplayRules,
} from '../../../utils/change-metadata-util';
import {fireAlert, fire, fireReload} from '../../../utils/event-util';
import {
  EditRevisionInfo,
  isDefined,
  ParsedChangeInfo,
} from '../../../types/types';
import {
  AutocompleteQuery,
  AutocompleteSuggestion,
} from '../../shared/gr-autocomplete/gr-autocomplete';
import {getRevertCreatedChangeIds} from '../../../utils/message-util';
import {Interaction} from '../../../constants/reporting';
import {getApprovalInfo, getCodeReviewLabel} from '../../../utils/label-util';
import {LitElement, css, html, nothing, PropertyValues} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {sharedStyles} from '../../../styles/shared-styles';
import {fontStyles} from '../../../styles/gr-font-styles';
import {changeMetadataStyles} from '../../../styles/gr-change-metadata-shared-styles';
import {when} from 'lit/directives/when.js';
import {createSearchUrl} from '../../../models/views/search';
import {createChangeUrl} from '../../../models/views/change';
import {getChangeWeblinks} from '../../../utils/weblink-util';
import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {subscribe} from '../../lit/subscription-controller';
import {userModelToken} from '../../../models/user/user-model';
import {resolve} from '../../../models/dependency';
import {configModelToken} from '../../../models/config/config-model';
import {changeModelToken} from '../../../models/change/change-model';
import {relatedChangesModelToken} from '../../../models/change/related-changes-model';
import {truncatePath} from '../../../utils/path-list-util';

const HASHTAG_ADD_MESSAGE = 'Add Hashtag';

export enum ChangeRole {
  OWNER = 'owner',
  UPLOADER = 'uploader',
  AUTHOR = 'author',
  COMMITTER = 'committer',
}

export interface CommitInfoWithRequiredCommit extends CommitInfo {
  // gr-change-view always assigns commit to CommitInfo
  commit: CommitId;
}

const SubmitTypeLabel = new Map<SubmitType, string>([
  [SubmitType.FAST_FORWARD_ONLY, 'Fast Forward Only'],
  [SubmitType.MERGE_IF_NECESSARY, 'Merge if Necessary'],
  [SubmitType.REBASE_IF_NECESSARY, 'Rebase if Necessary'],
  [SubmitType.MERGE_ALWAYS, 'Always Merge'],
  [SubmitType.REBASE_ALWAYS, 'Rebase Always'],
  [SubmitType.CHERRY_PICK, 'Cherry Pick'],
]);

const NOT_CURRENT_MESSAGE = 'Not current - rebase possible';

interface PushCertificateValidationInfo {
  class: string;
  icon: string;
  message: string;
}

@customElement('gr-change-metadata')
export class GrChangeMetadata extends LitElement {
  @query('#webLinks') webLinks?: HTMLElement;

  // TODO: Convert to @state. That requires the change model to keep track of
  // current revision actions. Then we can also get rid of the
  // `revision-actions-changed` event.
  @property({type: Boolean}) parentIsCurrent?: boolean;

  @state() change?: ParsedChangeInfo;

  @state() revertedChange?: ChangeInfo;

  @state() account?: AccountDetailInfo;

  @state() revision?: RevisionInfo | EditRevisionInfo;

  @state() serverConfig?: ServerInfo;

  @state() repoConfig?: ConfigInfo;

  @state() mutable = false;

  @state() readonly notCurrentMessage = NOT_CURRENT_MESSAGE;

  @state() topicReadOnly = true;

  @state() hashtagReadOnly = true;

  @state() pushCertificateValidation?: PushCertificateValidationInfo;

  @state() settingTopic = false;

  @state() currentParents: ParentCommitInfo[] = [];

  @state() showAllSections = false;

  @state() queryTopic?: AutocompleteQuery;

  @state() queryHashtag?: AutocompleteQuery;

  private restApiService = getAppContext().restApiService;

  private readonly reporting = getAppContext().reportingService;

  private readonly getUserModel = resolve(this, userModelToken);

  private readonly getConfigModel = resolve(this, configModelToken);

  private readonly getChangeModel = resolve(this, changeModelToken);

  private readonly getRelatedChangesModel = resolve(
    this,
    relatedChangesModelToken
  );

  constructor() {
    super();
    subscribe(
      this,
      () => this.getConfigModel().serverConfig$,
      serverConfig => (this.serverConfig = serverConfig)
    );
    subscribe(
      this,
      () => this.getConfigModel().repoConfig$,
      repoConfig => (this.repoConfig = repoConfig)
    );
    subscribe(
      this,
      () => this.getUserModel().account$,
      account => (this.account = account)
    );
    subscribe(
      this,
      () => this.getChangeModel().change$,
      change => (this.change = change)
    );
    subscribe(
      this,
      () => this.getChangeModel().revision$,
      revision => (this.revision = revision)
    );
    subscribe(
      this,
      () => this.getRelatedChangesModel().revertingChange$,
      revertingChange => (this.revertedChange = revertingChange)
    );
    this.queryTopic = (input: string) => this.getTopicSuggestions(input);
    this.queryHashtag = (input: string) => this.getHashtagSuggestions(input);
  }

  static override get styles() {
    return [
      sharedStyles,
      fontStyles,
      changeMetadataStyles,
      css`
        :host {
          display: table;
        }
        gr-submit-requirements {
          --requirements-horizontal-padding: var(--metadata-horizontal-padding);
        }
        gr-editable-label {
          max-width: 9em;
        }
        gr-weblink {
          display: block;
        }
        gr-account-chip[disabled],
        gr-linked-chip[disabled] {
          opacity: 0;
          pointer-events: none;
        }
        .hashtagChip {
          padding-bottom: var(--spacing-s);
        }
        /* consistent with section .title, .value */
        .hashtagChip:not(last-of-type) {
          padding-bottom: var(--spacing-s);
        }
        .hashtagChip:last-of-type {
          display: inline;
          vertical-align: top;
        }
        .parentList.merge {
          list-style-type: decimal;
          padding-left: var(--spacing-l);
        }
        .parentList gr-commit-info {
          display: inline-block;
        }
        .hideDisplay,
        #parentNotCurrentMessage {
          display: none;
        }
        .icon {
          margin: -3px 0;
        }
        .icon.help,
        .icon.notTrusted {
          color: var(--warning-foreground);
        }
        .icon.invalid {
          color: var(--negative-red-text-color);
        }
        .icon.trusted {
          color: var(--positive-green-text-color);
        }
        .parentList.notCurrent.nonMerge #parentNotCurrentMessage {
          --arrow-color: var(--warning-foreground);
          display: inline-block;
        }
        .oldSeparatedSection {
          margin-top: var(--spacing-l);
          padding: var(--spacing-m) 0;
        }
        .separatedSection {
          padding: var(--spacing-m) 0;
        }
        .hashtag gr-linked-chip,
        .topic gr-linked-chip {
          --linked-chip-text-color: var(--link-color);
        }
        gr-reviewer-list {
          --account-max-length: 100px;
          max-width: 285px;
        }
        .metadata-title {
          color: var(--deemphasized-text-color);
          padding-left: var(--metadata-horizontal-padding);
        }
        .metadata-header {
          display: flex;
          justify-content: space-between;
          align-items: flex-end;
          /* The goal is to achieve alignment of the owner account chip and the
         commit message box. Their top border should be on the same line. */
          margin-bottom: var(--spacing-s);
        }
        .show-all-button gr-icon {
          color: inherit;
          font-size: 18px;
        }
        gr-vote-chip {
          --gr-vote-chip-width: 14px;
          --gr-vote-chip-height: 14px;
        }
      `,
    ];
  }

  override render() {
    if (!this.change) return nothing;
    return html`<div>
      <div class="metadata-header">
        <h3 class="metadata-title heading-3">Change Info</h3>
        ${this.renderShowAllButton()}
      </div>
      ${this.renderSubmitted()} ${this.renderUpdated()} ${this.renderOwner()}
      ${this.renderNonOwner(ChangeRole.UPLOADER)}
      ${this.renderNonOwner(ChangeRole.AUTHOR)}
      ${this.renderNonOwner(ChangeRole.COMMITTER)} ${this.renderReviewers()}
      ${this.renderCCs()} ${this.renderProjectBranch()} ${this.renderParent()}
      ${this.renderMergedAs()} ${this.renderShowRevertCreatedAs()}
      ${this.renderTopic()} ${this.renderCherryPickOf()}
      ${this.renderRevertOf()} ${this.renderStrategy()} ${this.renderHashTags()}
      ${this.renderSubmitRequirements()} ${this.renderWeblinks()}
      <gr-endpoint-decorator name="change-metadata-item">
        <gr-endpoint-param
          name="labels"
          .value=${{...this.change?.labels}}
        ></gr-endpoint-param>
        <gr-endpoint-param
          name="change"
          .value=${this.change}
        ></gr-endpoint-param>
        <gr-endpoint-param
          name="revision"
          .value=${this.revision}
        ></gr-endpoint-param>
      </gr-endpoint-decorator>
    </div>`;
  }

  private renderShowAllButton() {
    return html`<gr-button
      link
      class="show-all-button"
      @click=${this.onShowAllClick}
      >${this.showAllSections ? 'Show less' : 'Show all'}
      <gr-icon icon="expand_more" ?hidden=${this.showAllSections}></gr-icon>
      <gr-icon icon="expand_less" ?hidden=${!this.showAllSections}></gr-icon>
    </gr-button>`;
  }

  private renderSubmitted() {
    if (!this.change!.submitted) return nothing;
    return html`<section class=${this.computeDisplayState(Metadata.SUBMITTED)}>
      <span class="title">Submitted</span>
      <span class="value">
        <gr-date-formatter
          withTooltip
          .dateStr=${this.change!.submitted}
          showYesterday
        ></gr-date-formatter>
      </span>
    </section> `;
  }

  private renderUpdated() {
    return html`<section class=${this.computeDisplayState(Metadata.UPDATED)}>
      <span class="title">
        <gr-tooltip-content
          has-tooltip
          title="Last update of (meta)data for this change."
        >
          Updated
        </gr-tooltip-content>
      </span>
      <span class="value">
        <gr-date-formatter
          withTooltip
          .dateStr=${this.change!.updated}
          showYesterday
        ></gr-date-formatter>
      </span>
    </section>`;
  }

  private renderOwner() {
    const change = this.change!;
    return html`<section class=${this.computeDisplayState(Metadata.OWNER)}>
      <span class="title">
        <gr-tooltip-content
          has-tooltip
          title="This user created or uploaded the first patchset of this change."
        >
          Owner
        </gr-tooltip-content>
      </span>
      <span class="value">
        <gr-account-chip
          .account=${change.owner}
          .change=${change}
          highlightAttention
          .vote=${this.computeVote(change.owner)}
          .label=${this.computeCodeReviewLabel()}
        >
          <gr-vote-chip
            slot="vote-chip"
            .vote=${this.computeVote(change.owner)}
            .label=${this.computeCodeReviewLabel()}
            circle-shape
          ></gr-vote-chip>
        </gr-account-chip>
        ${when(
          this.pushCertificateValidation,
          () => html`<gr-tooltip-content
            has-tooltip
            title=${this.pushCertificateValidation!.message}
          >
            <gr-icon
              icon=${this.pushCertificateValidation!.icon}
              class="icon ${this.pushCertificateValidation!.class}"
            ></gr-icon>
          </gr-tooltip-content>`
        )}
      </span>
    </section>`;
  }

  renderNonOwner(role: ChangeRole) {
    if (!this.getNonOwnerRole(role)) return nothing;
    let title = '';
    let name = '';
    if (role === ChangeRole.UPLOADER) {
      title =
        "This user uploaded the patchset to Gerrit (typically by running the 'git push' command).";
      name = 'Uploader';
    } else if (role === ChangeRole.AUTHOR) {
      title = 'This user wrote the code change.';
      name = 'Author';
    } else if (role === ChangeRole.COMMITTER) {
      title =
        'This user committed the code change to the Git repository (typically to the local Git repo before uploading).';
      name = 'Committer';
    }
    return html`<section>
      <span class="title">
        <gr-tooltip-content has-tooltip .title=${title}>
          ${name}
        </gr-tooltip-content>
      </span>
      <span class="value">
        <gr-account-chip
          .account=${this.getNonOwnerRole(role)}
          .change=${this.change}
          ?highlightAttention=${role === ChangeRole.UPLOADER}
          .vote=${this.computeVoteForRole(role)}
          .label=${this.computeCodeReviewLabel()}
        >
          <gr-vote-chip
            slot="vote-chip"
            .vote=${this.computeVoteForRole(role)}
            .label=${this.computeCodeReviewLabel()}
            circle-shape
          ></gr-vote-chip>
        </gr-account-chip>
      </span>
    </section>`;
  }

  private renderReviewers() {
    return html`<section class=${this.computeDisplayState(Metadata.REVIEWERS)}>
      <span class="title">Reviewers</span>
      <span class="value">
        <gr-reviewer-list
          .change=${this.change}
          ?mutable=${this.mutable}
          reviewers-only
          .account=${this.account}
        ></gr-reviewer-list>
      </span>
    </section>`;
  }

  private renderCCs() {
    return html`<section class=${this.computeDisplayState(Metadata.CC)}>
      <span class="title">CC</span>
      <span class="value">
        <gr-reviewer-list
          .change=${this.change}
          ?mutable=${this.mutable}
          ccs-only
          .account=${this.account}
        ></gr-reviewer-list>
      </span>
    </section>`;
  }

  private renderProjectBranch() {
    const change = this.change!;
    return when(
      this.computeShowRepoBranchTogether(),
      () =>
        html`<section class=${this.computeDisplayState(Metadata.REPO_BRANCH)}>
          <span class="title">
            <gr-tooltip-content
              has-tooltip
              title="Repository and branch that the change will be merged into if submitted."
            >
              Repo | Branch
            </gr-tooltip-content>
          </span>
          <span class="value">
            <a href=${this.computeProjectUrl(change.project)}
              >${change.project}</a
            >
            |
            <a href=${this.computeBranchUrl(change.project, change.branch)}
              >${change.branch}</a
            >
          </span>
        </section>`,

      () => html`<section
          class=${this.computeDisplayState(Metadata.REPO_BRANCH)}
        >
          <span class="title">
            <gr-tooltip-content
              has-tooltip
              title="Repository that the change will be merged into if submitted."
            >
              Repo
            </gr-tooltip-content>
          </span>
          <span class="value">
            <a
              href=${this.computeProjectUrl(change.project)}
              .title=${change.project}
            >
              ${truncatePath(change.project, 3)}
            </a>
          </span>
        </section>
        <section class=${this.computeDisplayState(Metadata.REPO_BRANCH)}>
          <span class="title">
            <gr-tooltip-content
              has-tooltip
              title="Branch that the change will be merged into if submitted."
            >
              Branch
            </gr-tooltip-content>
          </span>
          <span class="value">
            <a href=${this.computeBranchUrl(change.project, change.branch)}>
              <gr-limited-text
                limit="40"
                .text=${change.branch}
              ></gr-limited-text>
            </a>
          </span>
        </section>`
    );
  }

  private renderParent() {
    return html`<section class=${this.computeDisplayState(Metadata.PARENT)}>
      <span class="title"
        >${this.currentParents.length > 1 ? 'Parents' : 'Parent'}</span
      >
      <span class="value">
        <ol class=${this.computeParentListClass()}>
          ${this.currentParents.map(
            parent => html` <li>
              <gr-commit-info .commitInfo=${parent}></gr-commit-info>
              <gr-tooltip-content
                id="parentNotCurrentMessage"
                has-tooltip
                show-icon
                .title=${this.notCurrentMessage}
              ></gr-tooltip-content>
            </li>`
          )}
        </ol>
      </span>
    </section>`;
  }

  private renderMergedAs() {
    const changeMerged = this.change?.status === ChangeStatus.MERGED;
    if (!changeMerged) return nothing;
    return html`<section class=${this.computeDisplayState(Metadata.MERGED_AS)}>
      <span class="title">Merged As</span>
      <span class="value">
        <gr-commit-info
          .commitInfo=${this.computeMergedCommitInfo(
            this.change?.current_revision,
            this.change?.revisions
          )}
        ></gr-commit-info>
      </span>
    </section>`;
  }

  private renderShowRevertCreatedAs() {
    if (!this.showRevertCreatedAs()) return nothing;

    return html`<section
      class=${this.computeDisplayState(Metadata.REVERT_CREATED_AS)}
    >
      <span class="title">${this.getRevertSectionTitle()}</span>
      <span class="value">
        <gr-commit-info
          .commitInfo=${this.computeRevertCommit()}
        ></gr-commit-info>
      </span>
    </section>`;
  }

  private renderTopic() {
    const showTopic = this.change?.topic || !this.topicReadOnly;
    if (!showTopic) return nothing;

    return html`<section
      class="topic ${this.computeDisplayState(Metadata.TOPIC, this.account)}"
    >
      <span class="title">Topic</span>
      <span class="value">
        ${when(
          this.showTopicChip(),
          () => html` <gr-linked-chip
            .text=${this.change?.topic}
            limit="40"
            href=${createSearchUrl({topic: this.change!.topic!})}
            ?removable=${!this.topicReadOnly}
            @remove=${this.handleTopicRemoved}
          ></gr-linked-chip>`
        )}
        ${when(
          this.showAddTopic(),
          () =>
            html` <gr-editable-label
              class="topicEditableLabel"
              labelText="Set topic"
              .confirmLabel=${'Set Topic'}
              .value=${this.change?.topic}
              maxLength="1024"
              .placeholder=${this.computeTopicPlaceholder()}
              ?readOnly=${this.topicReadOnly}
              @changed=${this.handleTopicChanged}
              showAsEditPencil
              autocomplete
              .query=${this.queryTopic}
            ></gr-editable-label>`
        )}
      </span>
    </section>`;
  }

  private renderCherryPickOf() {
    if (!this.showCherryPickOf()) return nothing;
    return html` <section
      class=${this.computeDisplayState(Metadata.CHERRY_PICK_OF)}
    >
      <span class="title">Cherry pick of</span>
      <span class="value">
        <a
          href=${this.computeCherryPickOfUrl(
            this.change?.cherry_pick_of_change,
            this.change?.cherry_pick_of_patch_set,
            this.change?.project
          )}
        >
          <gr-limited-text
            text="${this.change?.cherry_pick_of_change},${this.change
              ?.cherry_pick_of_patch_set}"
            limit="40"
          >
          </gr-limited-text>
        </a>
      </span>
    </section>`;
  }

  private renderRevertOf() {
    if (!this.change?.revert_of) return nothing;
    return html` <section class=${this.computeDisplayState(Metadata.REVERT_OF)}>
      <span class="title">Revert of</span>
      <span class="value">
        <a
          href=${createChangeUrl({
            changeNum: this.change.revert_of,
            repo: this.change.project,
            usp: 'metadata',
          })}
          >${this.change.revert_of}</a
        >
      </span>
    </section>`;
  }

  private renderStrategy() {
    if (!changeIsOpen(this.change)) return nothing;
    return html`<section
      class="strategy ${this.computeDisplayState(Metadata.STRATEGY)}"
    >
      <span class="title">Strategy</span>
      <span class="value">${this.computeStrategy()}</span>
    </section>`;
  }

  private renderHashTags() {
    return html`<section
      class="hashtag ${this.computeDisplayState(Metadata.HASHTAGS)}"
    >
      <span class="title">Hashtags</span>
      <span class="value">
        ${(this.change?.hashtags ?? []).map(
          hashtag => html`<gr-linked-chip
            class="hashtagChip"
            .text=${hashtag}
            href=${this.computeHashtagUrl(hashtag)}
            ?removable=${!this.hashtagReadOnly}
            @remove=${this.handleHashtagRemoved}
            limit="40"
          >
          </gr-linked-chip>`
        )}
        ${when(
          !this.hashtagReadOnly,
          () => html`
            <gr-editable-label
              uppercase
              labelText="Add a hashtag"
              .placeholder=${this.computeHashtagPlaceholder()}
              .readOnly=${this.hashtagReadOnly}
              @changed=${this.handleHashtagChanged}
              showAsEditPencil
              autocomplete
              .query=${this.queryHashtag}
            ></gr-editable-label>
          `
        )}
      </span>
    </section>`;
  }

  private renderSubmitRequirements() {
    return html`<div class="separatedSection">
      <gr-submit-requirements
        .change=${this.change}
        .account=${this.account}
        .mutable=${this.mutable}
      ></gr-submit-requirements>
    </div>`;
  }

  private renderWeblinks() {
    const webLinks = this.computeWebLinks();
    if (!webLinks.length) return nothing;
    return html`<section id="webLinks">
      <span class="title">Links</span>
      <span class="value">
        ${webLinks.map(info => html`<gr-weblink .info=${info}></gr-weblink>`)}
      </span>
    </section>`;
  }

  override willUpdate(changedProperties: PropertyValues) {
    if (changedProperties.has('account')) {
      this.mutable = this.computeIsMutable();
    }
    if (changedProperties.has('mutable') || changedProperties.has('change')) {
      this.topicReadOnly = this.computeTopicReadOnly();
      this.hashtagReadOnly = this.computeHashtagReadOnly();
    }
    if (changedProperties.has('change')) {
      this.settingTopic = false;
    }
    if (
      changedProperties.has('serverConfig') ||
      changedProperties.has('change') ||
      changedProperties.has('repoConfig')
    ) {
      this.pushCertificateValidation = this.computePushCertificateValidation();
    }
    if (changedProperties.has('revision') || changedProperties.has('change')) {
      this.currentParents = this.computeParents();
    }
  }

  // private but used in test
  computeWebLinks(): WebLinkInfo[] {
    return getChangeWeblinks(
      this.revision?.commit?.web_links,
      this.serverConfig
    );
  }

  private computeStrategy() {
    if (!this.change?.submit_type) {
      return '';
    }

    return SubmitTypeLabel.get(this.change.submit_type);
  }

  // private but used in test
  computeLabelNames(labels?: LabelNameToInfoMap) {
    return labels ? Object.keys(labels).sort() : [];
  }

  // private but used in test
  async handleTopicChanged(e: CustomEvent<string>) {
    assertIsDefined(this.change, 'change');
    const topic = e.detail.length ? e.detail : undefined;
    this.settingTopic = true;
    try {
      fireAlert(this, 'Saving topic and reloading ...');
      await this.restApiService.setChangeTopic(this.change._number, topic);
    } finally {
      this.settingTopic = false;
    }
    fire(this, 'hide-alert', {});
    fireReload(this);
  }

  // private but used in test
  showAddTopic() {
    const hasTopic = !!this.change?.topic;
    return !hasTopic && !this.settingTopic && this.topicReadOnly === false;
  }

  // private but used in test
  showTopicChip() {
    const hasTopic = !!this.change?.topic;
    return hasTopic && !this.settingTopic;
  }

  // private but used in test
  showCherryPickOf() {
    const hasCherryPickOf =
      !!this.change?.cherry_pick_of_change &&
      !!this.change?.cherry_pick_of_patch_set;
    return hasCherryPickOf;
  }

  // private but used in test
  async handleHashtagChanged(e: CustomEvent<string>) {
    assertIsDefined(this.change, 'change');
    const newHashtag = e.detail.length ? e.detail : undefined;
    if (!newHashtag?.length) return;
    fireAlert(this, 'Saving hashtag and reloading ...');
    await this.restApiService.setChangeHashtag(this.change._number, {
      add: [newHashtag as Hashtag],
    });
    fire(this, 'hide-alert', {});
    fireReload(this);
  }

  // private but used in test
  computeTopicReadOnly() {
    return !this.mutable || !this.change?.actions?.topic?.enabled;
  }

  // private but used in test
  computeHashtagReadOnly() {
    return !this.mutable || !this.change?.actions?.hashtags?.enabled;
  }

  private computeTopicPlaceholder() {
    // Action items in Material Design are uppercase -- placeholder label text
    // is sentence case.
    return this.topicReadOnly ? 'No topic' : 'Set Topic';
  }

  private computeHashtagPlaceholder() {
    return this.hashtagReadOnly ? '' : HASHTAG_ADD_MESSAGE;
  }

  /**
   * private but used in test
   *
   * @return object representing data for the push validation.
   */
  computePushCertificateValidation():
    | PushCertificateValidationInfo
    | undefined {
    if (!this.change || !this.serverConfig?.receive?.enable_signed_push)
      return undefined;

    if (!this.isEnabledSignedPushOnRepo()) {
      return undefined;
    }
    const rev = this.change.revisions[this.change.current_revision];
    if (!rev.push_certificate?.key) {
      return {
        class: 'help filled',
        icon: 'help',
        message: 'This patch set was created without a push certificate',
      };
    }

    const key = rev.push_certificate.key;
    switch (key.status) {
      case GpgKeyInfoStatus.BAD:
        return {
          class: 'invalid',
          icon: 'close',
          message: this.problems('Push certificate is invalid', key),
        };
      case GpgKeyInfoStatus.OK:
        return {
          class: 'notTrusted filled',
          icon: 'info',
          message: this.problems(
            'Push certificate is valid, but key is not trusted',
            key
          ),
        };
      case GpgKeyInfoStatus.TRUSTED:
        return {
          class: 'trusted',
          icon: 'check',
          message: this.problems(
            'Push certificate is valid and key is trusted',
            key
          ),
        };
      case undefined:
        // TODO(TS): Process it correctly
        throw new Error('deleted certificate');
      default:
        assertNever(key.status, `unknown certificate status: ${key.status}`);
    }
  }

  // private but used in test
  isEnabledSignedPushOnRepo() {
    if (!this.repoConfig?.enable_signed_push) return false;

    const enableSignedPush = this.repoConfig.enable_signed_push;
    return (
      (enableSignedPush.configured_value ===
        InheritedBooleanInfoConfiguredValue.INHERIT &&
        enableSignedPush.inherited_value) ||
      enableSignedPush.configured_value ===
        InheritedBooleanInfoConfiguredValue.TRUE
    );
  }

  private problems(msg: string, key: GpgKeyInfo) {
    if (!key?.problems || key.problems.length === 0) {
      return msg;
    }

    return [msg + ':'].concat(key.problems).join('\n');
  }

  private computeShowRepoBranchTogether() {
    const {project, branch} = this.change!;
    return !!project && !!branch && project.length + branch.length < 40;
  }

  private computeProjectUrl(project?: RepoName) {
    if (!project) return '';
    return createSearchUrl({repo: project});
  }

  private computeBranchUrl(project?: RepoName, branch?: BranchName) {
    if (!project || !branch || !this.change || !this.change.status) return '';
    return createSearchUrl({
      branch,
      repo: project,
      statuses:
        this.change.status === ChangeStatus.NEW
          ? ['open']
          : [this.change.status.toLowerCase()],
    });
  }

  private computeCherryPickOfUrl(
    change?: NumericChangeId,
    patchset?: RevisionPatchSetNum,
    project?: RepoName
  ) {
    if (!change || !project) {
      return '';
    }
    return createChangeUrl({
      changeNum: change,
      repo: project,
      usp: 'metadata',
      patchNum: patchset,
    });
  }

  private computeHashtagUrl(hashtag: Hashtag) {
    return createSearchUrl({hashtag, statuses: ['open', 'merged']});
  }

  private async handleTopicRemoved(e: Event) {
    assertIsDefined(this.change, 'change');
    const target = e.composedPath()[0] as GrLinkedChip;
    target.disabled = true;
    try {
      fireAlert(this, 'Removing topic and reloading ...');
      await this.restApiService.setChangeTopic(this.change._number);
    } finally {
      target.disabled = false;
    }
    fire(this, 'hide-alert', {});
    fireReload(this);
  }

  // private but used in test
  async handleHashtagRemoved(e: Event) {
    e.preventDefault();
    assertIsDefined(this.change, 'change');
    const target = e.target as GrLinkedChip;
    target.disabled = true;
    try {
      fireAlert(this, 'Removing hashtag and reloading ...');
      await this.restApiService.setChangeHashtag(this.change._number, {
        remove: [target.text as Hashtag],
      });
    } finally {
      target.disabled = false;
    }
    fire(this, 'hide-alert', {});
    fireReload(this);
  }

  private computeDisplayState(section: Metadata, account?: AccountDetailInfo) {
    // special case for Topic - show always for owners, others when set
    if (section === Metadata.TOPIC) {
      if (
        this.showAllSections ||
        isOwner(this.change, account) ||
        isSectionSet(section, this.change)
      ) {
        return '';
      } else {
        return 'hideDisplay';
      }
    }
    if (
      this.showAllSections ||
      DisplayRules.ALWAYS_SHOW.includes(section) ||
      (DisplayRules.SHOW_IF_SET.includes(section) &&
        isSectionSet(section, this.change))
    ) {
      return '';
    }
    return 'hideDisplay';
  }

  // private but used in test
  computeMergedCommitInfo(
    currentrevision?: CommitId,
    revisions?: {[revisionId: string]: RevisionInfo | EditRevisionInfo}
  ): CommitInfo | undefined {
    if (!currentrevision || !revisions) return;
    const rev = revisions[currentrevision];
    if (!rev || !rev.commit) return;
    // CommitInfo.commit is optional. Set commit in all cases to avoid error
    // in <gr-commit-info>. @see Issue 5337
    if (!rev.commit.commit) {
      rev.commit.commit = currentrevision;
    }
    return rev.commit;
  }

  private getRevertSectionTitle() {
    return this.revertedChange?.status === ChangeStatus.MERGED
      ? 'Revert Submitted As'
      : 'Revert Created As';
  }

  // private but used in test
  showRevertCreatedAs() {
    if (!this.change?.messages) return false;
    return getRevertCreatedChangeIds(this.change.messages).length > 0;
  }

  // private but used in test
  computeRevertCommit(): CommitInfo | undefined {
    const {revertedChange, change} = this;
    if (revertedChange?.current_revision && revertedChange?.revisions) {
      // TODO(TS): Fix typing
      return {
        commit: this.computeMergedCommitInfo(
          revertedChange.current_revision,
          revertedChange.revisions
        ),
      } as CommitInfo;
    }
    if (!change?.messages) return undefined;
    // TODO(TS): Fix typing
    return {
      commit: getRevertCreatedChangeIds(change.messages)?.[0],
    } as unknown as CommitInfo;
  }

  // private but used in test
  onShowAllClick() {
    this.showAllSections = !this.showAllSections;
    this.reporting.reportInteraction(Interaction.TOGGLE_SHOW_ALL_BUTTON, {
      sectionName: 'metadata',
      toState: this.showAllSections ? 'Show all' : 'Show less',
    });
  }

  /**
   * Get the user with the specified role on the change. Returns undefined if the
   * user with that role is the same as the owner.
   * private but used in test
   */
  getNonOwnerRole(role: ChangeRole) {
    if (!this.change?.revisions?.[this.change.current_revision])
      return undefined;

    const rev = this.change.revisions[this.change.current_revision];
    if (!rev) return undefined;

    if (
      role === ChangeRole.UPLOADER &&
      rev.uploader &&
      this.change.owner._account_id !== rev.uploader._account_id
    ) {
      return rev.uploader;
    }

    if (
      role === ChangeRole.AUTHOR &&
      rev.commit?.author &&
      this.change.owner.email !== rev.commit.author.email
    ) {
      return rev.commit.author;
    }

    if (
      role === ChangeRole.COMMITTER &&
      rev.commit?.committer &&
      this.change.owner.email !== rev.commit.committer.email &&
      !(
        rev.uploader?.email && rev.uploader.email === rev.commit.committer.email
      )
    ) {
      return rev.commit.committer;
    }

    return undefined;
  }

  // private but used in test
  computeParents(): ParentCommitInfo[] {
    const {change, revision} = this;
    if (!revision?.commit) {
      if (!change?.current_revision) return [];
      const newRevision = change.revisions[change.current_revision];
      return newRevision?.commit?.parents ?? [];
    }
    return revision?.commit?.parents ?? [];
  }

  // private but used in test
  computeParentListClass() {
    return [
      'parentList',
      this.currentParents.length > 1 ? 'merge' : 'nonMerge',
      this.parentIsCurrent ? 'current' : 'notCurrent',
    ].join(' ');
  }

  private computeIsMutable() {
    return !!this.account && !!Object.keys(this.account).length;
  }

  editTopic() {
    if (this.topicReadOnly || !this.change || this.change.topic) {
      return;
    }
    const topicEditableLabel = this.shadowRoot!.querySelector<GrEditableLabel>(
      '.topicEditableLabel'
    );
    if (topicEditableLabel) {
      topicEditableLabel.open();
    }
  }

  private getTopicSuggestions(
    input: string
  ): Promise<AutocompleteSuggestion[]> {
    return this.restApiService
      .getChangesWithSimilarTopic(input, throwingErrorCallback)
      .then(response =>
        (response ?? [])
          .map(change => change.topic)
          .filter(isDefined)
          .filter(unique)
          .map(topic => {
            return {name: topic, value: topic};
          })
      );
  }

  private getHashtagSuggestions(
    input: string
  ): Promise<AutocompleteSuggestion[]> {
    return this.restApiService
      .getChangesWithSimilarHashtag(input, throwingErrorCallback)
      .then(response =>
        (response ?? [])
          .flatMap(change => change.hashtags ?? [])
          .filter(isDefined)
          .filter(unique)
          .map(hashtag => {
            return {name: hashtag, value: hashtag};
          })
      );
  }

  private computeVoteForRole(role: ChangeRole) {
    const reviewer = this.getNonOwnerRole(role);
    if (reviewer && isAccount(reviewer)) {
      return this.computeVote(reviewer);
    } else {
      return;
    }
  }

  private computeVote(reviewer: AccountInfo): ApprovalInfo | undefined {
    const codeReviewLabel = this.computeCodeReviewLabel();
    if (!codeReviewLabel || !isDetailedLabelInfo(codeReviewLabel)) return;
    return getApprovalInfo(codeReviewLabel, reviewer);
  }

  private computeCodeReviewLabel(): LabelInfo | undefined {
    if (!this.change?.labels) return;
    return getCodeReviewLabel(this.change.labels);
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-change-metadata': GrChangeMetadata;
  }
}
