/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../admin/gr-create-change-dialog/gr-create-change-dialog';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-dialog/gr-dialog';
import '../../shared/gr-dropdown/gr-dropdown';
import '../../shared/gr-icon/gr-icon';
import '../gr-confirm-abandon-dialog/gr-confirm-abandon-dialog';
import '../gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog';
import '../gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog';
import '../gr-confirm-move-dialog/gr-confirm-move-dialog';
import '../gr-confirm-rebase-dialog/gr-confirm-rebase-dialog';
import '../gr-confirm-revert-dialog/gr-confirm-revert-dialog';
import '../gr-confirm-submit-dialog/gr-confirm-submit-dialog';
import '../../../styles/shared-styles';
import {navigationToken} from '../../core/gr-navigation/gr-navigation';
import {getAppContext} from '../../../services/app-context';
import {
  CURRENT,
  hasEditBasedOnCurrentPatchSet,
} from '../../../utils/patch-set-util';
import {
  changeIsOpen,
  isOwner,
  listChangesOptionsToHex,
} from '../../../utils/change-util';
import {
  ChangeStatus,
  DraftsAction,
  HttpMethod,
  NotifyType,
} from '../../../constants/constants';
import {TargetElement} from '../../../api/plugin';
import {
  AccountInfo,
  ActionInfo,
  ActionNameToActionInfoMap,
  BranchName,
  ChangeActionDialog,
  ChangeInfo,
  CherryPickInput,
  CommentThread,
  CommitId,
  InheritedBooleanInfo,
  isDetailedLabelInfo,
  isQuickLabelInfo,
  LabelInfo,
  ListChangesOption,
  NumericChangeId,
  PatchSetNumber,
  RequestPayload,
  RevertSubmissionInfo,
  ReviewInput,
} from '../../../types/common';
import {GrConfirmAbandonDialog} from '../gr-confirm-abandon-dialog/gr-confirm-abandon-dialog';
import {GrDialog} from '../../shared/gr-dialog/gr-dialog';
import {GrCreateChangeDialog} from '../../admin/gr-create-change-dialog/gr-create-change-dialog';
import {GrConfirmSubmitDialog} from '../gr-confirm-submit-dialog/gr-confirm-submit-dialog';
import {
  ConfirmRevertEventDetail,
  GrConfirmRevertDialog,
  RevertType,
} from '../gr-confirm-revert-dialog/gr-confirm-revert-dialog';
import {GrConfirmMoveDialog} from '../gr-confirm-move-dialog/gr-confirm-move-dialog';
import {GrConfirmCherrypickDialog} from '../gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog';
import {GrConfirmCherrypickConflictDialog} from '../gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog';
import {
  ConfirmRebaseEventDetail,
  GrConfirmRebaseDialog,
} from '../gr-confirm-rebase-dialog/gr-confirm-rebase-dialog';
import {GrButton} from '../../shared/gr-button/gr-button';
import {
  GrChangeActionsElement,
  UIActionInfo,
} from '../../shared/gr-js-api-interface/gr-change-actions-js-api';
import {
  fire,
  fireAlert,
  fireError,
  fireNoBubbleNoCompose,
} from '../../../utils/event-util';
import {
  getApprovalInfo,
  getVotingRange,
  StandardLabels,
} from '../../../utils/label-util';
import {
  ActionPriority,
  ActionType,
  ChangeActions,
  PrimaryActionKey,
  RevisionActions,
} from '../../../api/change-actions';
import {ErrorCallback} from '../../../api/rest';
import {GrDropdown} from '../../shared/gr-dropdown/gr-dropdown';
import {resolve} from '../../../models/dependency';
import {changeModelToken} from '../../../models/change/change-model';
import {sharedStyles} from '../../../styles/shared-styles';
import {LitElement, PropertyValues, css, html, nothing} from 'lit';
import {customElement, query, state} from 'lit/decorators.js';
import {ifDefined} from 'lit/directives/if-defined.js';
import {assertIsDefined, queryAll, uuid} from '../../../utils/common-util';
import {Interaction} from '../../../constants/reporting';
import {rootUrl} from '../../../utils/url-util';
import {createSearchUrl} from '../../../models/views/search';
import {createChangeUrl} from '../../../models/views/change';
import {storageServiceToken} from '../../../services/storage/gr-storage_impl';
import {ShowRevisionActionsDetail} from '../../shared/gr-js-api-interface/gr-js-api-types';
import {whenVisible} from '../../../utils/dom-util';
import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {modalStyles} from '../../../styles/gr-modal-styles';
import {subscribe} from '../../lit/subscription-controller';
import {userModelToken} from '../../../models/user/user-model';
import {ParsedChangeInfo} from '../../../types/types';
import {configModelToken} from '../../../models/config/config-model';
import {readJSONResponsePayload} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {when} from 'lit/directives/when.js';

const ERR_BRANCH_EMPTY = 'The destination branch can’t be empty.';
const ERR_COMMIT_EMPTY = 'The commit message can’t be empty.';
const ERR_REVISION_ACTIONS = 'Couldn’t load revision actions.';

export enum LabelStatus {
  /**
   * This label provides what is necessary for submission.
   */
  OK = 'OK',
  /**
   * This label prevents the change from being submitted.
   */
  REJECT = 'REJECT',
  /**
   * The label may be set, but it's neither necessary for submission
   * nor does it block submission if set.
   */
  MAY = 'MAY',
  /**
   * The label is required for submission, but has not been satisfied.
   */
  NEED = 'NEED',
  /**
   * The label is required for submission, but is impossible to complete.
   * The likely cause is access has not been granted correctly by the
   * project owner or site administrator.
   */
  IMPOSSIBLE = 'IMPOSSIBLE',
  OPTIONAL = 'OPTIONAL',
}

const ActionLoadingLabels: {[actionKey: string]: string} = {
  abandon: 'Abandoning...',
  cherrypick: 'Cherry-picking...',
  delete: 'Deleting...',
  move: 'Moving..',
  rebase: 'Rebasing...',
  restore: 'Restoring...',
  revert: 'Reverting...',
  submit: 'Submitting...',
};

const ADDITIONAL_ACTION_KEY_PREFIX = '__additionalAction_';

interface QuickApproveUIActionInfo extends UIActionInfo {
  key: string;
  payload?: RequestPayload;
}

const QUICK_APPROVE_ACTION: QuickApproveUIActionInfo = {
  __key: 'review',
  __type: ActionType.CHANGE,
  enabled: true,
  key: 'review',
  label: 'Quick approve',
  method: HttpMethod.POST,
};

function isQuickApproveAction(
  action: UIActionInfo
): action is QuickApproveUIActionInfo {
  return (action as QuickApproveUIActionInfo).key === QUICK_APPROVE_ACTION.key;
}

const DOWNLOAD_ACTION: UIActionInfo = {
  enabled: true,
  label: 'Download patch',
  title: 'Open download dialog',
  __key: 'download',
  __primary: false,
  __type: ActionType.REVISION,
};

const INCLUDED_IN_ACTION: UIActionInfo = {
  enabled: true,
  label: 'Included In',
  title: 'Open Included In dialog',
  __key: 'includedIn',
  __primary: false,
  __type: ActionType.CHANGE,
};

const REBASE_EDIT: UIActionInfo = {
  enabled: true,
  label: 'Rebase edit',
  title: 'Rebase change edit',
  __key: 'rebaseEdit',
  __primary: false,
  __type: ActionType.CHANGE,
  method: HttpMethod.POST,
};

const PUBLISH_EDIT: UIActionInfo = {
  enabled: true,
  label: 'Publish edit',
  title: 'Publish change edit',
  __key: 'publishEdit',
  __primary: false,
  __type: ActionType.CHANGE,
  method: HttpMethod.POST,
};

const DELETE_EDIT: UIActionInfo = {
  enabled: true,
  label: 'Delete edit',
  title: 'Delete change edit',
  __key: 'deleteEdit',
  __primary: false,
  __type: ActionType.CHANGE,
  method: HttpMethod.DELETE,
};

const EDIT: UIActionInfo = {
  enabled: true,
  label: 'Edit',
  title: 'Edit this change',
  __key: 'edit',
  __primary: false,
  __type: ActionType.CHANGE,
};

const STOP_EDIT: UIActionInfo = {
  enabled: true,
  label: 'Stop editing',
  title: 'Stop editing this change',
  __key: 'stopEdit',
  __primary: false,
  __type: ActionType.CHANGE,
};

// Set of keys that have icons.
const ACTIONS_WITH_ICONS = new Map<
  string,
  Pick<UIActionInfo, 'filled' | 'icon'>
>([
  [ChangeActions.ABANDON, {icon: 'block'}],
  [ChangeActions.DELETE_EDIT, {icon: 'delete', filled: true}],
  [ChangeActions.EDIT, {icon: 'edit', filled: true}],
  [ChangeActions.PUBLISH_EDIT, {icon: 'publish', filled: true}],
  [ChangeActions.READY, {icon: 'visibility', filled: true}],
  [ChangeActions.REBASE_EDIT, {icon: 'rebase_edit'}],
  [RevisionActions.REBASE, {icon: 'rebase'}],
  [ChangeActions.RESTORE, {icon: 'history'}],
  [ChangeActions.REVERT, {icon: 'undo'}],
  [ChangeActions.STOP_EDIT, {icon: 'stop', filled: true}],
  [QUICK_APPROVE_ACTION.key, {icon: 'check'}],
  [RevisionActions.SUBMIT, {icon: 'done_all'}],
]);

const EDIT_ACTIONS: Set<string> = new Set([
  ChangeActions.DELETE_EDIT,
  ChangeActions.EDIT,
  ChangeActions.PUBLISH_EDIT,
  ChangeActions.REBASE_EDIT,
  ChangeActions.STOP_EDIT,
]);

const AWAIT_CHANGE_ATTEMPTS = 5;
const AWAIT_CHANGE_TIMEOUT_MS = 1000;

const SKIP_ACTION_KEYS: string[] = [
  // REVIEWED/UNREVIEWED is made obsolete by AttentionSet. Once the
  // backend stops supporting (UN)REVIEWED, we can remove these.
  ChangeActions.REVIEWED,
  ChangeActions.UNREVIEWED,
  // REVERT_SUBMISSION is folded into the dialog for REVERT.
  ChangeActions.REVERT_SUBMISSION,
];

export function assertUIActionInfo(action?: ActionInfo): UIActionInfo {
  // TODO(TS): Remove this function. The gr-change-actions adds properties
  // to existing ActionInfo objects instead of creating a new objects. This
  // function checks, that 'action' has all property required by UIActionInfo.
  // In the future, we should avoid updates of an existing ActionInfos and
  // instead create a new object to make code cleaner. However, at the current
  // state this is unsafe, because other code can expect these properties to be
  // set in ActionInfo.
  if (!action) {
    throw new Error('action is undefined');
  }
  const result = action as UIActionInfo;
  if (result.__key === undefined || result.__type === undefined) {
    throw new Error('action is not an UIActionInfo');
  }
  return result;
}

interface MenuAction {
  name: string;
  id: string;
  action: UIActionInfo;
  tooltip?: string;
}

interface OverflowAction {
  type: ActionType;
  key: string;
}

interface ActionPriorityOverride {
  type: ActionType.CHANGE | ActionType.REVISION;
  key: string;
  priority: ActionPriority;
}

@customElement('gr-change-actions')
export class GrChangeActions
  extends LitElement
  implements GrChangeActionsElement
{
  /**
   * Fired when the change should be reloaded.
   *
   * @event reload
   */

  /**
   * Fired when an action is tapped.
   *
   * @event custom-tap - naming pattern: <action key>-tap
   */

  @query('#mainContent') mainContent?: Element;

  @query('#actionsModal') actionsModal?: HTMLDialogElement;

  @query('#confirmRebase') confirmRebase?: GrConfirmRebaseDialog;

  @query('#confirmCherrypick') confirmCherrypick?: GrConfirmCherrypickDialog;

  @query('#confirmCherrypickConflict')
  confirmCherrypickConflict?: GrConfirmCherrypickConflictDialog;

  @query('#confirmMove') confirmMove?: GrConfirmMoveDialog;

  @query('#confirmRevertDialog') confirmRevertDialog?: GrConfirmRevertDialog;

  @query('#confirmAbandonDialog') confirmAbandonDialog?: GrConfirmAbandonDialog;

  @query('#confirmSubmitDialog') confirmSubmitDialog?: GrConfirmSubmitDialog;

  @query('#createFollowUpDialog') createFollowUpDialog?: GrDialog;

  @query('#createFollowUpChange') createFollowUpChange?: GrCreateChangeDialog;

  @query('#confirmDeleteDialog') confirmDeleteDialog?: GrDialog;

  @query('#confirmDeleteEditDialog') confirmDeleteEditDialog?: GrDialog;

  @query('#confirmPublishEditDialog') confirmPublishEditDialog?: GrDialog;

  @query('#moreActions') moreActions?: GrDropdown;

  @query('#secondaryActions') secondaryActions?: HTMLElement;

  @state() change?: ParsedChangeInfo;

  @state() actions: ActionNameToActionInfoMap = {};

  @state() primaryActionKeys: PrimaryActionKey[] = [
    ChangeActions.READY,
    RevisionActions.SUBMIT,
  ];

  @state() _hideQuickApproveAction = false;

  @state() account?: AccountInfo;

  @state() changeNum?: NumericChangeId;

  @state() changeStatus?: ChangeStatus;

  @state() mergeable?: boolean;

  @state() commitNum?: CommitId;

  @state() latestPatchNum?: PatchSetNumber;

  @state() commitMessage = '';

  // The unfiltered result of calling `restApiService.getChangeRevisionActions()`.
  // The DOWNLOAD action is also added to it in `actionsChanged()`.
  @state() revisionActions?: ActionNameToActionInfoMap;

  @state() privateByDefault?: InheritedBooleanInfo;

  @state() actionLoadingMessage = '';

  @state() inProgressActionKeys = new Set<string>();

  @state() allActionValues: UIActionInfo[] = [];

  @state() topLevelActions?: UIActionInfo[];

  @state() topLevelPrimaryActions?: UIActionInfo[];

  @state() topLevelSecondaryActions?: UIActionInfo[];

  @state() menuActions?: MenuAction[];

  @state() overflowActions: OverflowAction[] = [
    {
      type: ActionType.CHANGE,
      key: ChangeActions.WIP,
    },
    {
      type: ActionType.CHANGE,
      key: ChangeActions.DELETE,
    },
    {
      type: ActionType.REVISION,
      key: RevisionActions.CHERRYPICK,
    },
    {
      type: ActionType.CHANGE,
      key: ChangeActions.MOVE,
    },
    {
      type: ActionType.REVISION,
      key: RevisionActions.DOWNLOAD,
    },
    {
      type: ActionType.CHANGE,
      key: ChangeActions.REVIEWED,
    },
    {
      type: ActionType.CHANGE,
      key: ChangeActions.UNREVIEWED,
    },
    {
      type: ActionType.CHANGE,
      key: ChangeActions.PRIVATE,
    },
    {
      type: ActionType.CHANGE,
      key: ChangeActions.PRIVATE_DELETE,
    },
    {
      type: ActionType.CHANGE,
      key: ChangeActions.FOLLOW_UP,
    },
    {
      type: ActionType.CHANGE,
      key: ChangeActions.INCLUDED_IN,
    },
  ];

  @state() actionPriorityOverrides: ActionPriorityOverride[] = [];

  @state() additionalActions: UIActionInfo[] = [];

  @state() hiddenActions: string[] = [];

  @state() disabledMenuActions: string[] = [];

  @state() editPatchsetLoaded = false;

  @state() editMode = false;

  @state() editBasedOnCurrentPatchSet = true;

  @state() loggedIn = false;

  @state() pluginsLoaded = false;

  @state() threadsWithUnappliedSuggestions?: CommentThread[];

  private readonly restApiService = getAppContext().restApiService;

  private readonly reporting = getAppContext().reportingService;

  private readonly getPluginLoader = resolve(this, pluginLoaderToken);

  private readonly getUserModel = resolve(this, userModelToken);

  private readonly getConfigModel = resolve(this, configModelToken);

  private readonly getChangeModel = resolve(this, changeModelToken);

  private readonly getStorage = resolve(this, storageServiceToken);

  private readonly getNavigation = resolve(this, navigationToken);

  private readonly getCommentsModel = resolve(this, commentsModelToken);

  constructor() {
    super();
    subscribe(
      this,
      () => this.getChangeModel().latestPatchNum$,
      x => (this.latestPatchNum = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().patchsets$,
      x => (this.editBasedOnCurrentPatchSet = hasEditBasedOnCurrentPatchSet(x))
    );
    subscribe(
      this,
      () => this.getChangeModel().patchNum$,
      x => (this.editPatchsetLoaded = x === 'edit')
    );
    subscribe(
      this,
      () => this.getChangeModel().changeNum$,
      x => (this.changeNum = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().change$,
      x => (this.change = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().status$,
      x => (this.changeStatus = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().mergeable$,
      x => (this.mergeable = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().editMode$,
      x => (this.editMode = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().revision$,
      rev => (this.commitNum = rev?.commit?.commit)
    );
    subscribe(
      this,
      () => this.getChangeModel().latestRevision$,
      rev => (this.commitMessage = rev?.commit?.message ?? '')
    );
    subscribe(
      this,
      () => this.getUserModel().account$,
      x => (this.account = x)
    );
    subscribe(
      this,
      () => this.getUserModel().loggedIn$,
      x => (this.loggedIn = x)
    );
    subscribe(
      this,
      () => this.getPluginLoader().pluginsModel.pluginsLoaded$,
      x => (this.pluginsLoaded = x)
    );
    subscribe(
      this,
      () => this.getConfigModel().repoConfig$,
      config => (this.privateByDefault = config?.private_by_default)
    );
    subscribe(
      this,
      () => this.getCommentsModel().threadsWithUnappliedSuggestions$,
      x => (this.threadsWithUnappliedSuggestions = x)
    );
  }

  override connectedCallback() {
    super.connectedCallback();
    this.getPluginLoader().jsApiService.addElement(
      TargetElement.CHANGE_ACTIONS,
      this
    );
  }

  static override get styles() {
    return [
      sharedStyles,
      modalStyles,
      css`
        :host {
          display: flex;
          font-family: var(--font-family);
        }
        #actionLoadingMessage,
        #mainContent,
        section {
          display: flex;
        }
        #actionLoadingMessage,
        gr-button,
        gr-dropdown {
          /* px because don't have the same font size */
          margin-left: 8px;
        }
        gr-button {
          display: block;
        }
        #actionLoadingMessage {
          align-items: center;
          color: var(--deemphasized-text-color);
        }
        #confirmSubmitDialog .changeSubject {
          margin: var(--spacing-l);
          text-align: center;
        }
        gr-icon {
          color: inherit;
          margin-right: var(--spacing-xs);
        }
        #moreActions gr-icon {
          margin: 0;
        }
        #moreMessage,
        .hidden {
          display: none;
        }
        .info {
          background-color: var(--info-background);
          padding: var(--spacing-l) var(--spacing-xl);
          margin-bottom: var(--spacing-l);
        }
        .info gr-icon {
          color: var(--selected-foreground);
          margin-right: var(--spacing-xl);
        }
        @media screen and (max-width: 50em) {
          #mainContent {
            flex-wrap: wrap;
          }
          gr-button {
            --gr-button-padding: var(--spacing-m);
            white-space: nowrap;
          }
          gr-button,
          gr-dropdown {
            margin: 0;
          }
          #actionLoadingMessage {
            margin: var(--spacing-m);
            text-align: center;
          }
          #moreMessage {
            display: inline;
          }
        }
      `,
    ];
  }

  override render() {
    if (!this.change) return nothing;
    return html`
      <div id="mainContent">
        <span id="actionLoadingMessage" ?hidden=${!this.actionLoadingMessage}>
          ${this.actionLoadingMessage}
        </span>
        <section
          id="primaryActions"
          ?hidden=${this.isLoading() ||
          !this.topLevelActions ||
          !this.topLevelActions.length}
        >
          ${this.topLevelPrimaryActions?.map(action =>
            this.renderUIAction(action)
          )}
        </section>
        <section
          id="secondaryActions"
          ?hidden=${this.isLoading() ||
          !this.topLevelActions ||
          !this.topLevelActions.length}
        >
          ${this.topLevelSecondaryActions?.map(action =>
            this.renderUIAction(action)
          )}
        </section>
        <gr-button ?hidden=${!this.isLoading()}>Loading actions...</gr-button>
        <gr-dropdown
          id="moreActions"
          link
          .verticalOffset=${32}
          .horizontalAlign=${'right'}
          @tap-item=${this.handleOverflowItemTap}
          ?hidden=${this.isLoading() ||
          !this.menuActions ||
          !this.menuActions.length}
          .disabledIds=${this.disabledMenuActions}
          .items=${this.menuActions}
        >
          <gr-icon icon="more_vert" aria-labelledby="moreMessage"></gr-icon>
          <span id="moreMessage">More</span>
        </gr-dropdown>
      </div>
      <dialog id="actionsModal" tabindex="-1">
        <gr-confirm-rebase-dialog
          id="confirmRebase"
          class="confirmDialog"
          @confirm-rebase=${this.handleRebaseConfirm}
          @cancel=${this.handleConfirmDialogCancel}
          .disableActions=${this.inProgressActionKeys.has(
            RevisionActions.REBASE
          )}
          .branch=${this.change?.branch}
          .rebaseOnCurrent=${!!this.revisionActions?.rebase?.enabled}
        ></gr-confirm-rebase-dialog>
        <gr-confirm-cherrypick-dialog
          id="confirmCherrypick"
          class="confirmDialog"
          .changeStatus=${this.changeStatus}
          .commitMessage=${this.commitMessage}
          .commitNum=${this.commitNum}
          @confirm=${this.handleCherrypickConfirm}
          @cancel=${this.handleConfirmDialogCancel}
          .project=${this.change?.project}
        ></gr-confirm-cherrypick-dialog>
        <gr-confirm-cherrypick-conflict-dialog
          id="confirmCherrypickConflict"
          class="confirmDialog"
          @confirm=${this.handleCherrypickConflictConfirm}
          @cancel=${this.handleConfirmDialogCancel}
        ></gr-confirm-cherrypick-conflict-dialog>
        <gr-confirm-move-dialog
          id="confirmMove"
          class="confirmDialog"
          @confirm=${this.handleMoveConfirm}
          @cancel=${this.handleConfirmDialogCancel}
          .project=${this.change?.project}
        ></gr-confirm-move-dialog>
        <gr-confirm-revert-dialog
          id="confirmRevertDialog"
          class="confirmDialog"
          @confirm-revert=${this.handleRevertDialogConfirm}
          @cancel=${this.handleConfirmDialogCancel}
        ></gr-confirm-revert-dialog>
        <gr-confirm-abandon-dialog
          id="confirmAbandonDialog"
          class="confirmDialog"
          @confirm=${this.handleAbandonDialogConfirm}
          @cancel=${this.handleConfirmDialogCancel}
        ></gr-confirm-abandon-dialog>
        <gr-confirm-submit-dialog
          id="confirmSubmitDialog"
          class="confirmDialog"
          .action=${this.revisionActions?.submit}
          @cancel=${this.handleConfirmDialogCancel}
          @confirm=${this.handleSubmitConfirm}
        ></gr-confirm-submit-dialog>
        <gr-dialog
          id="createFollowUpDialog"
          class="confirmDialog"
          confirm-label="Create"
          @confirm=${this.handleCreateFollowUpChange}
          @cancel=${this.handleCloseCreateFollowUpChange}
        >
          <div class="header" slot="header">Create Follow-Up Change</div>
          <div class="main" slot="main">
            <gr-create-change-dialog
              id="createFollowUpChange"
              .branch=${this.change?.branch}
              .baseChange=${this.change?.id}
              .repoName=${this.change?.project}
              .privateByDefault=${this.privateByDefault}
            ></gr-create-change-dialog>
          </div>
        </gr-dialog>
        <gr-dialog
          id="confirmDeleteDialog"
          class="confirmDialog"
          confirm-label="Delete"
          confirm-on-enter=""
          @cancel=${this.handleConfirmDialogCancel}
          @confirm=${this.handleDeleteConfirm}
        >
          <div class="header" slot="header">Delete Change</div>
          <div class="main" slot="main">
            Do you really want to delete the change?
          </div>
        </gr-dialog>
        <gr-dialog
          id="confirmDeleteEditDialog"
          class="confirmDialog"
          confirm-label="Delete"
          confirm-on-enter=""
          @cancel=${this.handleConfirmDialogCancel}
          @confirm=${this.handleDeleteEditConfirm}
        >
          <div class="header" slot="header">Delete Change Edit</div>
          <div class="main" slot="main">
            Do you really want to delete the edit?
          </div>
        </gr-dialog>
        <gr-dialog
          id="confirmPublishEditDialog"
          class="confirmDialog"
          confirm-label="Publish"
          confirm-on-enter=""
          @cancel=${this.handleConfirmDialogCancel}
          @confirm=${this.handlePublishEditConfirm}
        >
          <div class="header" slot="header">Publish Change Edit</div>
          <div class="main" slot="main">
            ${when(
              this.numberOfThreadsWithUnappliedSuggestions() > 0,
              () => html`<p class="info">
                <gr-icon id="icon" icon="info" small></gr-icon>
                Heads Up! ${this.numberOfThreadsWithUnappliedSuggestions()}
                comments have suggestions you can apply before publishing
              </p>`
            )}
            Do you really want to publish the edit?
          </div>
        </gr-dialog>
      </dialog>
    `;
  }

  private renderUIAction(action: UIActionInfo) {
    return html`
      <gr-tooltip-content
        title=${ifDefined(action.title)}
        .hasTooltip=${!!action.title}
        ?position-below=${true}
      >
        <gr-button
          link
          class=${action.__key}
          data-action-key=${action.__key}
          data-label=${action.label}
          ?disabled=${this.calculateDisabled(action)}
          @click=${(e: MouseEvent) =>
            this.handleActionTap(e, action.__key, action.__type)}
        >
          ${this.renderUIActionIcon(action)} ${action.label}
        </gr-button>
      </gr-tooltip-content>
    `;
  }

  private renderUIActionIcon(action: UIActionInfo) {
    if (!action.icon) return nothing;
    return html`
      <gr-icon icon=${action.icon} ?filled=${action.filled}></gr-icon>
    `;
  }

  override willUpdate(changedProperties: PropertyValues) {
    if (changedProperties.has('change')) {
      this.reload();
      this.actions = this.change?.actions ?? {};
    }

    this.editStatusChanged();

    if (
      changedProperties.has('actions') ||
      changedProperties.has('revisionActions') ||
      changedProperties.has('additionalActions')
    ) {
      this.actionsChanged();
    }

    this.allActionValues = this.computeAllActions();
    this.topLevelActions = this.allActionValues.filter(a => {
      if (this.hiddenActions.includes(a.__key)) return false;
      if (this.editMode) return EDIT_ACTIONS.has(a.__key);
      return !this.isOverflowAction(a.__type, a.__key);
    });
    this.topLevelPrimaryActions = this.topLevelActions.filter(
      action => action.__primary
    );
    this.topLevelSecondaryActions = this.topLevelActions.filter(
      action => !action.__primary
    );
    this.menuActions = this.computeMenuActions();
  }

  reload() {
    if (!this.changeNum || !this.latestPatchNum || !this.change) {
      return Promise.resolve();
    }
    const change = this.change;
    this.revisionActions = undefined;
    return this.restApiService
      .getChangeRevisionActions(this.changeNum, this.latestPatchNum)
      .then(revisionActions => {
        this.revisionActions = revisionActions ?? {};
        this.sendShowRevisionActions({
          change: change as ChangeInfo,
          revisionActions: this.revisionActions,
        });
      })
      .catch(err => {
        fireAlert(this, ERR_REVISION_ACTIONS);
        throw err;
      });
  }

  private isLoading() {
    return (
      !this.pluginsLoaded ||
      !this.change ||
      this.mergeable === undefined ||
      this.revisionActions === undefined
    );
  }

  // private but used in test
  sendShowRevisionActions(detail: ShowRevisionActionsDetail) {
    this.getPluginLoader().jsApiService.handleShowRevisionActions(detail);
  }

  addActionButton(type: ActionType, label: string) {
    if (type !== ActionType.CHANGE && type !== ActionType.REVISION) {
      throw Error(`Invalid action type: ${type}`);
    }
    const action: UIActionInfo = {
      enabled: true,
      label,
      __type: type,
      __key: ADDITIONAL_ACTION_KEY_PREFIX + uuid(),
    };
    this.additionalActions.push(action);
    this.requestUpdate('additionalActions');
    return action.__key;
  }

  removeActionButton(key: string) {
    const idx = this.indexOfActionButtonWithKey(key);
    if (idx === -1) {
      return;
    }
    this.additionalActions.splice(idx, 1);
    this.requestUpdate('additionalActions');
  }

  setActionButtonProp<T extends keyof UIActionInfo>(
    key: string,
    prop: T,
    value: UIActionInfo[T]
  ) {
    this.additionalActions[this.indexOfActionButtonWithKey(key)][prop] = value;
    this.requestUpdate('additionalActions');
  }

  // TODO: Rename to toggleOverflow().
  setActionOverflow(type: ActionType, key: string, overflow: boolean) {
    if (type !== ActionType.CHANGE && type !== ActionType.REVISION) {
      throw Error(`Invalid action type given: ${type}`);
    }
    const isCurrentlyOverflow = this.isOverflowAction(type, key);
    if (overflow === isCurrentlyOverflow) {
      return;
    }

    // remove from overflowActions
    if (!overflow) {
      this.overflowActions = this.overflowActions.filter(
        action => action.type !== type || action.key !== key
      );
    }
    // add to overflowActions
    if (overflow) {
      this.overflowActions = [...this.overflowActions, {type, key}];
    }
  }

  setActionPriority(
    type: ActionType.CHANGE | ActionType.REVISION,
    key: string,
    priority: ActionPriority
  ) {
    if (type !== ActionType.CHANGE && type !== ActionType.REVISION) {
      throw Error(`Invalid action type given: ${type}`);
    }
    const index = this.actionPriorityOverrides.findIndex(
      action => action.type === type && action.key === key
    );
    const action: ActionPriorityOverride = {
      type,
      key,
      priority,
    };
    if (index !== -1) {
      this.actionPriorityOverrides[index] = action;
      this.requestUpdate('actionPriorityOverrides');
    } else {
      this.actionPriorityOverrides.push(action);
      this.requestUpdate('actionPriorityOverrides');
    }
  }

  setActionHidden(
    type: ActionType.CHANGE | ActionType.REVISION,
    key: string,
    hidden: boolean
  ) {
    if (type !== ActionType.CHANGE && type !== ActionType.REVISION) {
      throw Error(`Invalid action type given: ${type}`);
    }

    const idx = this.hiddenActions.indexOf(key);
    if (hidden && idx === -1) {
      this.hiddenActions.push(key);
      this.requestUpdate('hiddenActions');
    } else if (!hidden && idx !== -1) {
      this.hiddenActions.splice(idx, 1);
      this.requestUpdate('hiddenActions');
    }
  }

  getActionDetails(actionName: string) {
    if (this.revisionActions?.[actionName]) {
      return this.revisionActions[actionName];
    } else if (this.actions?.[actionName]) {
      return this.actions[actionName];
    } else {
      return undefined;
    }
  }

  private indexOfActionButtonWithKey(key: string) {
    for (let i = 0; i < this.additionalActions.length; i++) {
      if (this.additionalActions[i].__key === key) {
        return i;
      }
    }
    return -1;
  }

  private actionsChanged() {
    this.actionLoadingMessage = '';
    this.disabledMenuActions = [];

    if (this.revisionActions && !this.revisionActions.download) {
      this.revisionActions = {
        ...this.revisionActions,
        download: DOWNLOAD_ACTION,
      };
      fire(this, 'revision-actions-changed', {
        value: this.revisionActions,
      });
    }
    if (
      !this.actions.includedIn &&
      this.change?.status === ChangeStatus.MERGED
    ) {
      this.actions = {...this.actions, includedIn: INCLUDED_IN_ACTION};
    }
  }

  private editStatusChanged() {
    if (!this.change || !this.loggedIn) return;
    if (this.editPatchsetLoaded) {
      // Only show actions that mutate an edit if an actual edit patch set
      // is loaded.
      if (changeIsOpen(this.change)) {
        if (this.editBasedOnCurrentPatchSet) {
          if (!this.actions.publishEdit) {
            this.actions = {...this.actions, publishEdit: PUBLISH_EDIT};
          }
          delete this.actions.rebaseEdit;
        } else {
          if (!this.actions.rebaseEdit) {
            this.actions = {...this.actions, rebaseEdit: REBASE_EDIT};
          }
          delete this.actions.publishEdit;
        }
      }
      if (!this.actions.deleteEdit) {
        this.actions = {...this.actions, deleteEdit: DELETE_EDIT};
      }
    } else {
      delete this.actions.rebaseEdit;
      delete this.actions.publishEdit;
      delete this.actions.deleteEdit;
    }

    if (changeIsOpen(this.change)) {
      // Only show edit button if there is no edit patchset loaded and the
      // file list is not in edit mode.
      if (this.editPatchsetLoaded || this.editMode) {
        delete this.actions.edit;
      } else {
        if (!this.actions.edit) {
          this.actions = {...this.actions, edit: EDIT};
        }
      }
      // Only show STOP_EDIT if edit mode is enabled, but no edit patch set
      // is loaded.
      if (this.editMode && !this.editPatchsetLoaded) {
        if (!this.actions.stopEdit) {
          this.actions = {...this.actions, stopEdit: STOP_EDIT};
          fireAlert(this, 'Change is in edit mode');
        }
      } else {
        delete this.actions.stopEdit;
      }
    } else {
      // Remove edit button.
      delete this.actions.edit;
    }
  }

  private getValuesFor<T>(obj: {[key: string]: T}): T[] {
    return Object.keys(obj).map(key => obj[key]);
  }

  private getLabelStatus(label: LabelInfo): LabelStatus {
    if (isQuickLabelInfo(label)) {
      if (label.approved) {
        return LabelStatus.OK;
      } else if (label.rejected) {
        return LabelStatus.REJECT;
      }
    }
    if (label.optional) {
      return LabelStatus.OPTIONAL;
    } else {
      return LabelStatus.NEED;
    }
  }

  /**
   * Get highest score for last missing permitted label for current change.
   * Returns null if no labels permitted or more than one label missing.
   */
  private getTopMissingApproval() {
    if (!this.change || !this.change.labels || !this.change.permitted_labels) {
      return null;
    }
    if (this.change?.status === ChangeStatus.MERGED) {
      return null;
    }
    let result;
    for (const [label, labelInfo] of Object.entries(this.change.labels)) {
      if (!(label in this.change.permitted_labels)) {
        continue;
      }
      if (this.change.permitted_labels[label].length === 0) {
        continue;
      }
      const status = this.getLabelStatus(labelInfo);
      if (status === LabelStatus.NEED) {
        if (result) {
          // More than one label is missing, so check if Code Review can be
          // given
          result = null;
          break;
        }
        result = label;
      } else if (
        status === LabelStatus.REJECT ||
        status === LabelStatus.IMPOSSIBLE
      ) {
        return null;
      }
    }
    // Allow the user to use quick approve to vote the max score on code review
    // even if it is already granted by someone else. Does not apply if the
    // user owns the change or has already granted the max score themselves.
    const codeReviewLabel = this.change.labels[StandardLabels.CODE_REVIEW];
    const codeReviewPermittedValues =
      this.change.permitted_labels[StandardLabels.CODE_REVIEW];
    if (
      !result &&
      codeReviewLabel &&
      codeReviewPermittedValues &&
      this.account?._account_id &&
      isDetailedLabelInfo(codeReviewLabel) &&
      !isOwner(this.change, this.account) &&
      getApprovalInfo(codeReviewLabel, this.account)?.value !==
        getVotingRange(codeReviewLabel)?.max
    ) {
      result = StandardLabels.CODE_REVIEW;
    }

    if (result) {
      const labelInfo = this.change.labels[result];
      if (!isDetailedLabelInfo(labelInfo)) {
        return null;
      }
      const permittedValues = this.change.permitted_labels[result];
      const usersMaxPermittedScore =
        permittedValues[permittedValues.length - 1];
      const maxScoreForLabel = getVotingRange(labelInfo)?.max;
      if (Number(usersMaxPermittedScore) === maxScoreForLabel) {
        // Allow quick approve only for maximal score.
        return {
          label: result,
          score: usersMaxPermittedScore,
        };
      }
    }
    return null;
  }

  hideQuickApproveAction() {
    if (!this.topLevelSecondaryActions) {
      throw new Error('topLevelSecondaryActions must be set');
    }
    this.topLevelSecondaryActions = this.topLevelSecondaryActions.filter(
      sa => !isQuickApproveAction(sa)
    );
    this._hideQuickApproveAction = true;
  }

  private getQuickApproveAction(): QuickApproveUIActionInfo | null {
    if (this._hideQuickApproveAction) {
      return null;
    }
    const approval = this.getTopMissingApproval();
    if (!approval) {
      return null;
    }
    const action = {...QUICK_APPROVE_ACTION};
    action.label = approval.label + approval.score;

    const score = Number(approval.score);
    if (isNaN(score)) {
      return null;
    }

    const review: ReviewInput = {
      drafts: DraftsAction.PUBLISH_ALL_REVISIONS,
      labels: {
        [approval.label]: score,
      },
    };
    action.payload = review;
    return action;
  }

  private getActionValues(
    actionsChange: ActionNameToActionInfoMap | undefined,
    primariesChange: PrimaryActionKey[],
    additionalActionsChange: UIActionInfo[],
    type: ActionType
  ): UIActionInfo[] {
    if (!actionsChange || !primariesChange) {
      return [];
    }

    const actions = actionsChange;
    const primaryActionKeys = primariesChange;
    const result: UIActionInfo[] = [];
    const values: Array<ChangeActions | RevisionActions> =
      type === ActionType.CHANGE
        ? this.getValuesFor(ChangeActions)
        : this.getValuesFor(RevisionActions);

    const pluginActions: UIActionInfo[] = [];
    Object.keys(actions).forEach(a => {
      const action: UIActionInfo = actions[a] as UIActionInfo;
      action.__key = a;
      action.__type = type;
      action.__primary = primaryActionKeys.includes(a as PrimaryActionKey);
      // Plugin actions always contain ~ in the key.
      if (a.indexOf('~') !== -1) {
        this.populateActionUrl(action);
        pluginActions.push(action);
        // Add server-side provided plugin actions to overflow menu.
        this.overflowActions.push({
          type,
          key: a,
        });
        this.requestUpdate('overflowActions');
        return;
      } else if (!values.includes(a as PrimaryActionKey)) {
        return;
      }
      action.label = this.getActionLabel(action);

      // Triggers a re-render by ensuring object inequality.
      result.push({...action});
    });

    let additionalActions = additionalActionsChange;
    additionalActions = additionalActions
      .filter(a => a.__type === type)
      .map(a => {
        a.__primary = primaryActionKeys.includes(a.__key as PrimaryActionKey);
        // Triggers a re-render by ensuring object inequality.
        return {...a};
      });
    return result.concat(additionalActions).concat(pluginActions);
  }

  private populateActionUrl(action: UIActionInfo) {
    const patchNum =
      action.__type === ActionType.REVISION ? this.latestPatchNum : undefined;
    if (!this.changeNum) {
      return;
    }
    this.restApiService
      .getChangeActionURL(this.changeNum, patchNum, '/' + action.__key)
      .then(url => (action.__url = url));
  }

  /**
   * Given a change action, return a display label that uses the appropriate
   * casing or includes explanatory details.
   */
  private getActionLabel(action: UIActionInfo) {
    if (action.label === 'Delete') {
      // This label is common within change and revision actions. Make it more
      // explicit to the user.
      return 'Delete change';
    } else if (action.label === 'WIP') {
      return 'Mark as work in progress';
    }
    // Otherwise, just map the name to sentence case.
    return this.toSentenceCase(action.label);
  }

  /**
   * Capitalize the first letter and lowercase all others.
   *
   * private but used in test
   */
  toSentenceCase(s: string) {
    if (!s.length) {
      return '';
    }
    return s[0].toUpperCase() + s.slice(1).toLowerCase();
  }

  private computeLoadingLabel(action: string) {
    return ActionLoadingLabels[action] || 'Working...';
  }

  // private but used in test
  canSubmitChange() {
    if (!this.change) return false;
    const change = this.change as ChangeInfo;
    const revision = this.getRevision(change, this.latestPatchNum);
    return this.getPluginLoader().jsApiService.canSubmitChange(
      change,
      revision
    );
  }

  // private but used in test
  getRevision(change: ChangeInfo, patchNum?: PatchSetNumber) {
    for (const rev of Object.values(change.revisions ?? {})) {
      if (rev._number === patchNum) {
        return rev;
      }
    }
    return null;
  }

  showRevertDialog() {
    const change = this.change;
    if (!change) return;
    const query = `submissionid: "${change.submission_id}"`;
    /* A chromium plugin expects that the modifyRevertMsg hook will only
    be called after the revert button is pressed, hence we populate the
    revert dialog after revert button is pressed. */
    this.restApiService.getChanges(0, query).then(changes => {
      if (!changes) {
        this.reporting.error(
          'Change Actions',
          new Error('getChanges returns undefined')
        );
        return;
      }
      assertIsDefined(this.confirmRevertDialog, 'confirmRevertDialog');
      this.confirmRevertDialog.populate(
        change,
        this.commitMessage,
        changes.length
      );
      this.showActionDialog(this.confirmRevertDialog);
    });
  }

  showSubmitDialog() {
    if (!this.canSubmitChange()) {
      return;
    }
    assertIsDefined(this.confirmSubmitDialog, 'confirmSubmitDialog');
    this.showActionDialog(this.confirmSubmitDialog);
  }

  private handleActionTap(e: MouseEvent, key: string, type: string) {
    e.preventDefault();
    let el = e.target as Element;
    while (el.tagName.toLowerCase() !== 'gr-button') {
      if (!el.parentElement) {
        return;
      }
      el = el.parentElement;
    }

    if (
      key.startsWith(ADDITIONAL_ACTION_KEY_PREFIX) ||
      key.indexOf('~') !== -1
    ) {
      this.dispatchEvent(
        new CustomEvent(`${key}-tap`, {
          detail: {node: el},
          composed: true,
          bubbles: true,
        })
      );
      return;
    }
    this.handleAction(type as ActionType, key);
  }

  private handleOverflowItemTap(e: CustomEvent<MenuAction>) {
    e.preventDefault();
    const el = e.target as Element;
    const key = e.detail.action.__key;
    if (
      key.startsWith(ADDITIONAL_ACTION_KEY_PREFIX) ||
      key.indexOf('~') !== -1
    ) {
      this.dispatchEvent(
        new CustomEvent(`${key}-tap`, {
          detail: {node: el},
          composed: true,
          bubbles: true,
        })
      );
      return;
    }
    this.handleAction(e.detail.action.__type, e.detail.action.__key);
  }

  // private but used in test
  handleAction(type: ActionType, key: string) {
    this.reporting.reportInteraction(`${type}-${key}`);
    switch (type) {
      case ActionType.REVISION:
        this.handleRevisionAction(key);
        break;
      case ActionType.CHANGE:
        this.handleChangeAction(key);
        break;
      default:
        this.fireAction(
          this.prependSlash(key),
          assertUIActionInfo(this.actions[key]),
          false
        );
    }
  }

  // private but used in test
  handleChangeAction(key: string) {
    switch (key) {
      case ChangeActions.REVERT:
        this.showRevertDialog();
        break;
      case ChangeActions.ABANDON:
        assertIsDefined(this.confirmAbandonDialog, 'confirmAbandonDialog');
        this.showActionDialog(this.confirmAbandonDialog);
        break;
      case QUICK_APPROVE_ACTION.key: {
        const action = this.allActionValues.find(isQuickApproveAction);
        if (!action) {
          return;
        }
        this.fireAction(this.prependSlash(key), action, true, action.payload);
        break;
      }
      case ChangeActions.EDIT:
        this.handleEditTap();
        break;
      case ChangeActions.STOP_EDIT:
        this.handleStopEditTap();
        break;
      case ChangeActions.DELETE:
        this.handleDeleteTap();
        break;
      case ChangeActions.DELETE_EDIT:
        this.handleDeleteEditTap();
        break;
      case ChangeActions.FOLLOW_UP:
        this.handleFollowUpTap();
        break;
      case ChangeActions.WIP:
        this.handleWipTap();
        break;
      case ChangeActions.MOVE:
        this.handleMoveTap();
        break;
      case ChangeActions.PUBLISH_EDIT:
        this.handlePublishEditTap();
        break;
      case ChangeActions.REBASE_EDIT:
        this.handleRebaseEditTap();
        break;
      case ChangeActions.INCLUDED_IN:
        this.handleIncludedInTap();
        break;
      default:
        this.fireAction(
          this.prependSlash(key),
          assertUIActionInfo(this.actions[key]),
          false
        );
    }
  }

  private handleRevisionAction(key: string) {
    switch (key) {
      case RevisionActions.REBASE:
        assertIsDefined(this.confirmRebase, 'confirmRebase');
        this.showActionDialog(this.confirmRebase);
        this.confirmRebase.fetchRecentChanges();
        break;
      case RevisionActions.CHERRYPICK:
        this.handleCherrypickTap();
        break;
      case RevisionActions.DOWNLOAD:
        this.handleDownloadTap();
        break;
      case RevisionActions.SUBMIT:
        if (!this.canSubmitChange()) {
          return;
        }
        assertIsDefined(this.confirmSubmitDialog, 'confirmSubmitDialog');
        this.showActionDialog(this.confirmSubmitDialog);
        break;
      default:
        this.fireAction(
          this.prependSlash(key),
          assertUIActionInfo(this.revisionActions?.[key]),
          true
        );
    }
  }

  private prependSlash(key: string) {
    return key === '/' ? key : `/${key}`;
  }

  private calculateDisabled(action: UIActionInfo) {
    // TODO(b/270972983): Remove this special casing once the backend is more
    // aggressive about setting`enabled:true`.
    if (action.__key === 'rebase') return false;
    return !action.enabled;
  }

  private handleConfirmDialogCancel() {
    this.hideAllDialogs();
  }

  private hideAllDialogs() {
    assertIsDefined(this.confirmSubmitDialog, 'confirmSubmitDialog');
    const dialogEls = queryAll(this, '.confirmDialog');
    for (const dialogEl of dialogEls) {
      (dialogEl as HTMLElement).hidden = true;
    }
    assertIsDefined(this.actionsModal, 'actionsModal');
    this.actionsModal.close();
  }

  // private but used in test
  handleRebaseConfirm(e: CustomEvent<ConfirmRebaseEventDetail>) {
    assertIsDefined(this.confirmRebase, 'confirmRebase');
    assertIsDefined(this.actionsModal, 'actionsModal');
    const payload = {
      base: e.detail.base,
      allow_conflicts: e.detail.allowConflicts,
      on_behalf_of_uploader: e.detail.onBehalfOfUploader,
      committer_email: e.detail.committerEmail,
    };
    const rebaseChain = !!e.detail.rebaseChain;
    this.fireAction(
      rebaseChain ? '/rebase:chain' : '/rebase',
      assertUIActionInfo(this.revisionActions?.rebase),
      rebaseChain ? false : true,
      payload,
      {
        allow_conflicts: payload.allow_conflicts,
        on_behalf_of_uploader: payload.on_behalf_of_uploader,
      }
    );
  }

  // private but used in test
  handleCherrypickConfirm() {
    this.handleCherryPickRestApi(false);
  }

  // private but used in test
  handleCherrypickConflictConfirm() {
    this.handleCherryPickRestApi(true);
  }

  private handleCherryPickRestApi(conflicts: boolean) {
    assertIsDefined(this.confirmCherrypick, 'confirmCherrypick');
    assertIsDefined(this.actionsModal, 'actionsModal');
    const el = this.confirmCherrypick;
    if (!el.branch) {
      fireAlert(this, ERR_BRANCH_EMPTY);
      return;
    }
    if (!el.message) {
      fireAlert(this, ERR_COMMIT_EMPTY);
      return;
    }
    this.actionsModal.close();
    el.hidden = true;
    this.fireAction(
      '/cherrypick',
      assertUIActionInfo(this.revisionActions?.cherrypick),
      true,
      {
        destination: el.branch,
        base: el.baseCommit ? el.baseCommit : null,
        message: el.message,
        allow_conflicts: conflicts,
        committer_email: el.committerEmail ? el.committerEmail : null,
      }
    );
  }

  // private but used in test
  handleMoveConfirm() {
    assertIsDefined(this.confirmMove, 'confirmMove');
    assertIsDefined(this.actionsModal, 'actionsModal');
    const el = this.confirmMove;
    if (!el.branch) {
      fireAlert(this, ERR_BRANCH_EMPTY);
      return;
    }
    this.actionsModal.close();
    el.hidden = true;
    this.fireAction('/move', assertUIActionInfo(this.actions.move), false, {
      destination_branch: el.branch,
      message: el.message,
    });
  }

  private handleRevertDialogConfirm(e: CustomEvent<ConfirmRevertEventDetail>) {
    assertIsDefined(this.confirmRevertDialog, 'confirmRevertDialog');
    assertIsDefined(this.actionsModal, 'actionsModal');
    const revertType = e.detail.revertType;
    const message = e.detail.message;
    const el = this.confirmRevertDialog;
    this.actionsModal.close();
    el.hidden = true;
    switch (revertType) {
      case RevertType.REVERT_SINGLE_CHANGE:
        this.fireAction(
          '/revert',
          assertUIActionInfo(this.actions.revert),
          false,
          {message}
        );
        break;
      case RevertType.REVERT_SUBMISSION:
        // TODO(dhruvsri): replace with this.actions.revert_submission once
        // BE starts sending it again
        this.fireAction(
          '/revert_submission',
          {__key: 'revert_submission', method: HttpMethod.POST} as UIActionInfo,
          false,
          {message}
        );
        break;
      default:
        this.reporting.error(
          'Change Actions',
          new Error('invalid revert type')
        );
    }
  }

  // private but used in test
  handleAbandonDialogConfirm() {
    assertIsDefined(this.confirmAbandonDialog, 'confirmAbandonDialog');
    assertIsDefined(this.actionsModal, 'actionsModal');
    const el = this.confirmAbandonDialog;
    this.actionsModal.close();
    el.hidden = true;
    this.fireAction(
      '/abandon',
      assertUIActionInfo(this.actions.abandon),
      false,
      {
        message: el.message,
      }
    );
  }

  private handleCreateFollowUpChange() {
    assertIsDefined(this.createFollowUpChange, 'createFollowUpChange');
    this.createFollowUpChange.handleCreateChange();
    this.handleCloseCreateFollowUpChange();
  }

  private handleCloseCreateFollowUpChange() {
    assertIsDefined(this.actionsModal, 'actionsModal');
    this.actionsModal.close();
  }

  private handleDeleteConfirm() {
    this.hideAllDialogs();
    this.fireAction(
      '/',
      assertUIActionInfo(this.actions[ChangeActions.DELETE]),
      false
    );
  }

  private handleDeleteEditConfirm() {
    this.hideAllDialogs();

    // We need to make sure that all cached version of a change
    // edit are deleted.
    this.getStorage().eraseEditableContentItemsForChangeEdit(this.changeNum);

    this.fireAction(
      '/edit',
      assertUIActionInfo(this.actions.deleteEdit),
      false
    );
  }

  private handlePublishEditConfirm() {
    this.hideAllDialogs();

    if (!this.actions.publishEdit) return;

    // We need to make sure that all cached version of a change
    // edit are deleted.
    this.getStorage().eraseEditableContentItemsForChangeEdit(this.changeNum);

    this.fireAction(
      '/edit:publish',
      assertUIActionInfo(this.actions.publishEdit),
      false,
      {notify: NotifyType.OWNER_REVIEWERS}
    );
  }

  // private but used in test
  handleSubmitConfirm() {
    if (!this.canSubmitChange()) {
      return;
    }
    this.hideAllDialogs();
    this.fireAction(
      '/submit',
      assertUIActionInfo(this.revisionActions?.submit),
      true
    );
  }

  private isOverflowAction(type: string, key: string) {
    return this.overflowActions.some(
      action => action.type === type && action.key === key
    );
  }

  // private but used in test
  setLoadingOnButtonWithKey(action: UIActionInfo) {
    const key = action.__key;
    this.inProgressActionKeys.add(key);
    this.actionLoadingMessage = this.computeLoadingLabel(key);
    let buttonKey = key;
    // TODO(dhruvsri): clean this up later
    // If key is revert-submission, then button key should be 'revert'
    if (buttonKey === ChangeActions.REVERT_SUBMISSION) {
      // Revert submission button no longer exists
      buttonKey = ChangeActions.REVERT;
    }

    if (this.isOverflowAction(action.__type, buttonKey)) {
      this.disabledMenuActions.push(
        buttonKey === '/' ? 'delete-change' : `${buttonKey}-${action.__type}`
      );
      this.requestUpdate('disabledMenuActions');
      return () => {
        this.inProgressActionKeys.delete(key);
        this.actionLoadingMessage = '';
        this.disabledMenuActions = [];
        this.requestUpdate();
      };
    }

    // Otherwise it's a top-level action.
    const buttonEl = this.shadowRoot!.querySelector(
      `[data-action-key="${buttonKey}"]`
    ) as GrButton;
    if (!buttonEl) {
      throw new Error(`Can't find button by data-action-key '${buttonKey}'`);
    }
    buttonEl.setAttribute('loading', 'true');
    buttonEl.disabled = true;
    return () => {
      this.inProgressActionKeys.delete(action.__key);
      this.actionLoadingMessage = '';
      buttonEl.removeAttribute('loading');
      buttonEl.disabled = false;
      this.requestUpdate();
    };
  }

  // private but used in test
  fireAction(
    endpoint: string,
    action: UIActionInfo,
    revAction: boolean,
    payload?: RequestPayload,
    toReport?: Object
  ) {
    const cleanupFn = this.setLoadingOnButtonWithKey(action);
    this.reporting.reportInteraction(Interaction.CHANGE_ACTION_FIRED, {
      endpoint,
      toReport,
    });

    this.send(
      action.method,
      payload,
      endpoint,
      revAction,
      cleanupFn,
      action
    ).then(res => this.handleResponse(action, res));
  }

  // private but used in test
  showActionDialog(dialog: ChangeActionDialog) {
    this.hideAllDialogs();
    if (dialog.init) dialog.init();
    dialog.hidden = false;
    assertIsDefined(this.actionsModal, 'actionsModal');
    if (this.actionsModal.isConnected) this.actionsModal.showModal();
    whenVisible(dialog, () => {
      if (dialog.resetFocus) {
        dialog.resetFocus();
      }
    });
  }

  // TODO(rmistry): Redo this after
  // https://issues.gerritcodereview.com/issues/40004936 is resolved.
  // private but used in test
  setReviewOnRevert(newChangeId: NumericChangeId) {
    const review = this.getPluginLoader().jsApiService.getReviewPostRevert(
      this.change as ChangeInfo
    );
    if (!review) {
      return Promise.resolve(undefined);
    }
    return this.restApiService.saveChangeReview(newChangeId, CURRENT, review);
  }

  // private but used in test
  async handleResponse(action: UIActionInfo, response: Response | undefined) {
    if (!response?.ok) {
      return;
    }
    switch (action.__key) {
      case ChangeActions.REVERT: {
        const revertChangeInfo = (await readJSONResponsePayload(response))
          .parsed as unknown as ChangeInfo;
        this.restApiService.addRepoNameToCache(
          revertChangeInfo._number,
          revertChangeInfo.project
        );
        const reachable = await this.waitForChangeReachable(
          revertChangeInfo._number
        );
        if (!reachable) return;
        await this.setReviewOnRevert(revertChangeInfo._number);
        this.getNavigation().setUrl(
          createChangeUrl({change: revertChangeInfo})
        );
        break;
      }
      case RevisionActions.CHERRYPICK: {
        const cherrypickChangeInfo = (await readJSONResponsePayload(response))
          .parsed as unknown as ChangeInfo;
        this.restApiService.addRepoNameToCache(
          cherrypickChangeInfo._number,
          cherrypickChangeInfo.project
        );
        const reachable = this.waitForChangeReachable(
          cherrypickChangeInfo._number
        );
        if (!reachable) return;
        this.getNavigation().setUrl(
          createChangeUrl({change: cherrypickChangeInfo})
        );
        break;
      }
      case ChangeActions.DELETE:
        if (action.__type === ActionType.CHANGE) {
          this.getNavigation().setUrl(rootUrl());
        }
        break;
      case ChangeActions.WIP:
      case ChangeActions.DELETE_EDIT:
      case ChangeActions.PUBLISH_EDIT:
      case ChangeActions.REBASE_EDIT:
      case ChangeActions.REBASE:
      case ChangeActions.SUBMIT:
        // Hide rebase dialog only if the action succeeds
        this.actionsModal?.close();
        this.hideAllDialogs();
        this.getChangeModel().navigateToChangeResetReload();
        break;
      case ChangeActions.REVERT_SUBMISSION: {
        const revertSubmistionInfo = (await readJSONResponsePayload(response))
          .parsed as unknown as RevertSubmissionInfo;
        if (
          !revertSubmistionInfo.revert_changes ||
          !revertSubmistionInfo.revert_changes.length
        )
          return;
        /* If there is only 1 change then gerrit will automatically
          redirect to that change */
        const topic = revertSubmistionInfo.revert_changes[0].topic;
        this.getNavigation().setUrl(createSearchUrl({topic}));
        break;
      }
      default:
        this.getChangeModel().navigateToChangeResetReload();
        break;
    }
  }

  // private but used in test
  handleResponseError(
    action: UIActionInfo,
    response: Response | undefined | null,
    body?: RequestPayload
  ) {
    if (!response) {
      return Promise.resolve(() => {
        fireError(this, `Could not perform action '${action.__key}'`);
      });
    }
    if (action && action.__key === RevisionActions.CHERRYPICK) {
      if (
        response.status === 409 &&
        body &&
        !(body as CherryPickInput).allow_conflicts
      ) {
        assertIsDefined(
          this.confirmCherrypickConflict,
          'confirmCherrypickConflict'
        );
        this.showActionDialog(this.confirmCherrypickConflict);
        return;
      }
    }
    return response.text().then(errText => {
      fireError(this, `Could not perform action: ${errText}`);
      if (!errText.startsWith('Change is already up to date')) {
        throw Error(errText);
      }
    });
  }

  // private but used in test
  send(
    method: HttpMethod | undefined,
    payload: RequestPayload | undefined,
    actionEndpoint: string,
    revisionAction: boolean,
    cleanupFn: () => void,
    action: UIActionInfo
  ): Promise<Response | undefined> {
    const handleError: ErrorCallback = response => {
      cleanupFn.call(this);
      this.handleResponseError(action, response, payload);
    };
    const change = this.change;
    const changeNum = this.changeNum;
    if (!change || !changeNum) {
      return Promise.reject(
        new Error('Properties change and changeNum must be set.')
      );
    }
    return this.getChangeModel()
      .fetchChangeUpdates(change)
      .then(result => {
        if (!result.isLatest) {
          fire(this, 'show-alert', {
            message:
              'Cannot set label: a newer patch has been ' +
              'uploaded to this change.',
            action: 'Reload',
            callback: () => this.getChangeModel().navigateToChangeResetReload(),
          });

          // Because this is not a network error, call the cleanup function
          // but not the error handler.
          cleanupFn();

          return Promise.resolve(undefined);
        }
        const patchNum = revisionAction ? this.latestPatchNum : undefined;
        return this.restApiService
          .executeChangeAction(
            changeNum,
            method,
            actionEndpoint,
            patchNum,
            payload,
            handleError
          )
          .then(response => {
            cleanupFn.call(this);
            return response;
          });
      });
  }

  // private but used in test
  async handleCherrypickTap() {
    if (!this.change) {
      throw new Error('The change property must be set');
    }
    assertIsDefined(this.confirmCherrypick, 'confirmCherrypick');
    this.confirmCherrypick.branch = '' as BranchName;
    const changes = await this.getCherryPickChanges();
    if (!changes.length) return;
    this.confirmCherrypick.updateChanges(changes);
    this.showActionDialog(this.confirmCherrypick);
  }

  private async getCherryPickChanges() {
    if (!this.change) return [];
    if (!this.change.topic) return [this.change];
    const query = `topic: "${this.change.topic}"`;
    const options = listChangesOptionsToHex(
      ListChangesOption.MESSAGES,
      ListChangesOption.ALL_REVISIONS
    );
    return this.restApiService
      .getChanges(0, query, undefined, options)
      .then(changes => {
        if (!changes) {
          this.reporting.error(
            'Change Actions',
            new Error('getChanges returns undefined')
          );
          return [];
        }
        return changes;
      });
  }

  // private but used in test
  handleMoveTap() {
    assertIsDefined(this.confirmMove, 'confirmMove');
    this.confirmMove.branch = '' as BranchName;
    this.confirmMove.message = '';
    this.showActionDialog(this.confirmMove);
  }

  // private but used in test
  handleDownloadTap() {
    fire(this, 'download-tap', {});
  }

  // private but used in test
  handleIncludedInTap() {
    fire(this, 'included-tap', {});
  }

  // private but used in test
  handleDeleteTap() {
    assertIsDefined(this.confirmDeleteDialog, 'confirmDeleteDialog');
    this.showActionDialog(this.confirmDeleteDialog);
  }

  // private but used in test
  handleDeleteEditTap() {
    assertIsDefined(this.confirmDeleteEditDialog, 'confirmDeleteEditDialog');
    this.showActionDialog(this.confirmDeleteEditDialog);
  }

  private handleFollowUpTap() {
    assertIsDefined(this.createFollowUpDialog, 'createFollowUpDialog');
    this.showActionDialog(this.createFollowUpDialog);
  }

  private handleWipTap() {
    if (!this.actions.wip) {
      return;
    }
    this.fireAction('/wip', assertUIActionInfo(this.actions.wip), false);
  }

  private handlePublishEditTap() {
    if (this.numberOfThreadsWithUnappliedSuggestions() > 0) {
      assertIsDefined(
        this.confirmPublishEditDialog,
        'confirmPublishEditDialog'
      );
      this.showActionDialog(this.confirmPublishEditDialog);
    } else {
      // Skip confirmation dialog and publish immediately.
      this.handlePublishEditConfirm();
    }
  }

  private handleRebaseEditTap() {
    if (!this.actions.rebaseEdit) {
      return;
    }
    this.fireAction(
      '/edit:rebase',
      assertUIActionInfo(this.actions.rebaseEdit),
      false
    );
  }

  /**
   * Merge sources of change actions into a single ordered array of action
   * values.
   */
  private computeAllActions(): UIActionInfo[] {
    if (this.change === undefined) {
      return [];
    }

    const revisionActionValues = this.getActionValues(
      this.revisionActions,
      this.primaryActionKeys,
      this.additionalActions,
      ActionType.REVISION
    );
    const changeActionValues = this.getActionValues(
      this.actions,
      this.primaryActionKeys,
      this.additionalActions,
      ActionType.CHANGE
    );
    const quickApprove = this.getQuickApproveAction();
    if (quickApprove) {
      changeActionValues.unshift(quickApprove);
    }

    return revisionActionValues
      .concat(changeActionValues)
      .sort((a, b) => this.actionComparator(a, b))
      .map(action => {
        return {
          ...action,
          ...(ACTIONS_WITH_ICONS.get(action.__key) ?? {}),
        };
      })
      .filter(action => !this.shouldSkipAction(action));
  }

  private getActionPriority(action: UIActionInfo) {
    if (action.__type && action.__key) {
      const overrideAction = this.actionPriorityOverrides.find(
        i => i.type === action.__type && i.key === action.__key
      );

      if (overrideAction !== undefined) {
        return overrideAction.priority;
      }
    }
    if (action.__key === 'review') {
      return ActionPriority.REVIEW;
    } else if (action.__primary) {
      return ActionPriority.PRIMARY;
    } else if (action.__type === ActionType.CHANGE) {
      return ActionPriority.CHANGE;
    } else if (action.__type === ActionType.REVISION) {
      return ActionPriority.REVISION;
    }
    return ActionPriority.DEFAULT;
  }

  /**
   * Sort comparator to define the order of change actions.
   *
   * private but used in test
   */
  actionComparator(actionA: UIActionInfo, actionB: UIActionInfo) {
    const priorityDelta =
      this.getActionPriority(actionA) - this.getActionPriority(actionB);
    // Sort by the button label if same priority.
    if (priorityDelta === 0) {
      return actionA.label > actionB.label ? 1 : -1;
    } else {
      return priorityDelta;
    }
  }

  private shouldSkipAction(action: UIActionInfo) {
    return SKIP_ACTION_KEYS.includes(action.__key);
  }

  private computeMenuActions(): MenuAction[] {
    return this.allActionValues
      .filter(a => {
        const overflow = this.isOverflowAction(a.__type, a.__key);
        return overflow && !this.hiddenActions.includes(a.__key);
      })
      .map(action => {
        let key = action.__key;
        if (key === '/') {
          key = 'delete';
        }
        return {
          name: action.label,
          id: `${key}-${action.__type}`,
          action,
          tooltip: action.title,
        };
      });
  }

  /**
   * Occasionally, a change created by a change action is not yet known to the
   * API for a brief time. Wait for the given change number to be recognized.
   *
   * Returns a promise that resolves with true if a request is recognized, or
   * false if the change was never recognized after all attempts.
   *
   * private but used in test
   */
  waitForChangeReachable(changeNum: NumericChangeId): Promise<boolean> {
    let attemptsRemaining = AWAIT_CHANGE_ATTEMPTS;
    return new Promise(resolve => {
      const check = () => {
        attemptsRemaining--;
        // Pass a no-op error handler to avoid the "not found" error toast,
        // unless it's the last attempt
        this.restApiService
          .getChange(changeNum, attemptsRemaining !== 0 ? () => {} : undefined)
          .then(response => {
            // If the response is 404, the response will be undefined.
            if (response) {
              resolve(true);
              return;
            }

            if (attemptsRemaining) {
              setTimeout(check, AWAIT_CHANGE_TIMEOUT_MS);
            } else {
              resolve(false);
            }
          });
      };
      check();
    });
  }

  private handleEditTap() {
    fireNoBubbleNoCompose(this, 'edit-tap', {});
  }

  private handleStopEditTap() {
    fireNoBubbleNoCompose(this, 'stop-edit-tap', {});
  }

  private numberOfThreadsWithUnappliedSuggestions() {
    if (!this.threadsWithUnappliedSuggestions) return 0;
    return this.threadsWithUnappliedSuggestions.length;
  }
}

declare global {
  interface HTMLElementEventMap {
    'download-tap': CustomEvent<{}>;
    'edit-tap': CustomEvent<{}>;
    'included-tap': CustomEvent<{}>;
    'revision-actions-changed': CustomEvent<{value: ActionNameToActionInfoMap}>;
    'stop-edit-tap': CustomEvent<{}>;
  }
  interface HTMLElementTagNameMap {
    'gr-change-actions': GrChangeActions;
  }
}
