/**
 * @license
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import '../../../styles/shared-styles';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import '../../plugins/gr-endpoint-param/gr-endpoint-param';
import '../gr-button/gr-button';
import '../gr-dialog/gr-dialog';
import '../gr-date-formatter/gr-date-formatter';
import '../gr-formatted-text/gr-formatted-text';
import '../gr-icons/gr-icons';
import '../gr-overlay/gr-overlay';
import '../gr-rest-api-interface/gr-rest-api-interface';
import '../gr-storage/gr-storage';
import '../gr-textarea/gr-textarea';
import '../gr-tooltip-content/gr-tooltip-content';
import '../gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog';
import '../gr-account-label/gr-account-label';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-comment_html';
import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {getRootElement} from '../../../scripts/rootElement';
import {appContext} from '../../../services/app-context';
import {customElement, observe, property} from '@polymer/decorators';
import {RestApiService} from '../../../services/services/gr-rest-api/gr-rest-api';
import {GrTextarea} from '../gr-textarea/gr-textarea';
import {GrStorage, StorageLocation} from '../gr-storage/gr-storage';
import {GrOverlay} from '../gr-overlay/gr-overlay';
import {
  AccountDetailInfo,
  NumericChangeId,
  ConfigInfo,
  PatchSetNum,
} from '../../../types/common';
import {GrButton} from '../gr-button/gr-button';
import {GrConfirmDeleteCommentDialog} from '../gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog';
import {GrDialog} from '../gr-dialog/gr-dialog';
import {Side} from '../../../constants/constants';
import {
  isDraft,
  UIComment,
  UIDraft,
  UIRobot,
} from '../../diff/gr-comment-api/gr-comment-api';

const STORAGE_DEBOUNCE_INTERVAL = 400;
const TOAST_DEBOUNCE_INTERVAL = 200;

const SAVING_MESSAGE = 'Saving';
const DRAFT_SINGULAR = 'draft...';
const DRAFT_PLURAL = 'drafts...';
const SAVED_MESSAGE = 'All changes saved';
const UNSAVED_MESSAGE = 'Unable to save draft';

const REPORT_CREATE_DRAFT = 'CreateDraftComment';
const REPORT_UPDATE_DRAFT = 'UpdateDraftComment';
const REPORT_DISCARD_DRAFT = 'DiscardDraftComment';

const FILE = 'FILE';

export const __testOnly_UNSAVED_MESSAGE = UNSAVED_MESSAGE;

/**
 * All candidates tips to show, will pick randomly.
 */
const RESPECTFUL_REVIEW_TIPS = [
  'Assume competence.',
  'Provide rationale or context.',
  'Consider how comments may be interpreted.',
  'Avoid harsh language.',
  'Make your comments specific and actionable.',
  'When disagreeing, explain the advantage of your approach.',
];

interface CommentOverlays {
  confirmDelete?: GrOverlay | null;
  confirmDiscard?: GrOverlay | null;
}

export interface GrComment {
  $: {
    restAPI: RestApiService & Element;
    storage: GrStorage;
    container: HTMLDivElement;
    resolvedCheckbox: HTMLInputElement;
  };
}

export interface CommentEventDetail {
  patchNum?: PatchSetNum;
  comment?: UIComment;
}

@customElement('gr-comment')
export class GrComment extends KeyboardShortcutMixin(
  GestureEventListeners(LegacyElementMixin(PolymerElement))
) {
  static get template() {
    return htmlTemplate;
  }

  /**
   * Fired when the create fix comment action is triggered.
   *
   * @event create-fix-comment
   */

  /**
   * Fired when the show fix preview action is triggered.
   *
   * @event open-fix-preview
   */

  /**
   * Fired when this comment is discarded.
   *
   * @event comment-discard
   */

  /**
   * Fired when this comment is saved.
   *
   * @event comment-save
   */

  /**
   * Fired when this comment is updated.
   *
   * @event comment-update
   */

  /**
   * Fired when editing status changed.
   *
   * @event comment-editing-changed
   */

  /**
   * Fired when the comment's timestamp is tapped.
   *
   * @event comment-anchor-tap
   */

  @property({type: Number})
  changeNum?: NumericChangeId;

  @property({type: Object, notify: true, observer: '_commentChanged'})
  comment?: UIComment | UIRobot;

  @property({type: Array})
  comments?: (UIComment | UIRobot)[];

  @property({type: Boolean, reflectToAttribute: true})
  isRobotComment = false;

  @property({type: Boolean, reflectToAttribute: true})
  disabled = false;

  @property({type: Boolean, observer: '_draftChanged'})
  draft = false;

  @property({type: Boolean, observer: '_editingChanged'})
  editing = false;

  @property({type: Boolean, reflectToAttribute: true})
  discarding = false;

  @property({type: Boolean})
  hasChildren?: boolean;

  @property({type: String})
  patchNum?: PatchSetNum;

  @property({type: Boolean})
  showActions?: boolean;

  @property({type: Boolean})
  _showHumanActions?: boolean;

  @property({type: Boolean})
  _showRobotActions?: boolean;

  @property({
    type: Boolean,
    reflectToAttribute: true,
    observer: '_toggleCollapseClass',
  })
  collapsed = true;

  @property({type: Object})
  projectConfig?: ConfigInfo;

  @property({type: Boolean})
  robotButtonDisabled?: boolean;

  @property({type: Boolean})
  _hasHumanReply?: boolean;

  @property({type: Boolean})
  _isAdmin = false;

  @property({type: Object})
  _xhrPromise?: Promise<any>; // Used for testing.

  @property({type: String, observer: '_messageTextChanged'})
  _messageText = '';

  @property({type: String})
  commentSide?: Side;

  @property({type: String})
  side?: string;

  @property({type: Boolean})
  resolved?: boolean;

  // Intentional to share the object across instances.
  @property({type: Object})
  _numPendingDraftRequests: {number: number} = {number: 0};

  @property({type: Boolean})
  _enableOverlay = false;

  /**
   * Property for storing references to overlay elements. When the overlays
   * are moved to getRootElement() to be shown they are no-longer
   * children, so they can't be queried along the tree, so they are stored
   * here.
   */
  @property({type: Object})
  _overlays: CommentOverlays = {};

  @property({type: Boolean})
  _showRespectfulTip = false;

  @property({type: Boolean})
  showPatchset = true;

  @property({type: String})
  _respectfulReviewTip?: string;

  @property({type: Boolean})
  _respectfulTipDismissed = false;

  @property({type: Boolean})
  _unableToSave = false;

  @property({type: Object})
  _selfAccount?: AccountDetailInfo;

  get keyBindings() {
    return {
      'ctrl+enter meta+enter ctrl+s meta+s': '_handleSaveKey',
      esc: '_handleEsc',
    };
  }

  reporting = appContext.reportingService;

  /** @override */
  attached() {
    super.attached();
    this.$.restAPI.getAccount().then(account => {
      this._selfAccount = account;
    });
    if (this.editing) {
      this.collapsed = false;
    } else if (this.comment) {
      this.collapsed = !!this.comment.collapsed;
    }
    this._getIsAdmin().then(isAdmin => {
      this._isAdmin = !!isAdmin;
    });
  }

  /** @override */
  detached() {
    super.detached();
    this.cancelDebouncer('fire-update');
    if (this.textarea) {
      this.textarea.closeDropdown();
    }
  }

  _getAuthor(comment: UIComment) {
    return comment.author || this._selfAccount;
  }

  @observe('editing')
  _onEditingChange(editing?: boolean) {
    this.dispatchEvent(
      new CustomEvent('comment-editing-changed', {
        detail: !!editing,
        bubbles: true,
        composed: true,
      })
    );
    if (!editing) return;
    // visibility based on cache this will make sure we only and always show
    // a tip once every Math.max(a day, period between creating comments)
    const cachedVisibilityOfRespectfulTip = this.$.storage.getRespectfulTipVisibility();
    if (!cachedVisibilityOfRespectfulTip) {
      // we still want to show the tip with a probability of 30%
      if (this.getRandomNum(0, 3) >= 1) return;
      this._showRespectfulTip = true;
      const randomIdx = this.getRandomNum(0, RESPECTFUL_REVIEW_TIPS.length);
      this._respectfulReviewTip = RESPECTFUL_REVIEW_TIPS[randomIdx];
      this.reporting.reportInteraction('respectful-tip-appeared', {
        tip: this._respectfulReviewTip,
      });
      // update cache
      this.$.storage.setRespectfulTipVisibility();
    }
  }

  /** Set as a separate method so easy to stub. */
  getRandomNum(min: number, max: number) {
    return Math.floor(Math.random() * (max - min) + min);
  }

  _computeVisibilityOfTip(showTip: boolean, tipDismissed: boolean) {
    return showTip && !tipDismissed;
  }

  _dismissRespectfulTip() {
    this._respectfulTipDismissed = true;
    this.reporting.reportInteraction('respectful-tip-dismissed', {
      tip: this._respectfulReviewTip,
    });
    // add a 14-day delay to the tip cache
    this.$.storage.setRespectfulTipVisibility(/* delayDays= */ 14);
  }

  _onRespectfulReadMoreClick() {
    this.reporting.reportInteraction('respectful-read-more-clicked');
  }

  get textarea(): GrTextarea | null {
    return this.shadowRoot?.querySelector('#editTextarea') as GrTextarea | null;
  }

  get confirmDeleteOverlay() {
    if (!this._overlays.confirmDelete) {
      this._enableOverlay = true;
      flush();
      this._overlays.confirmDelete = this.shadowRoot?.querySelector(
        '#confirmDeleteOverlay'
      ) as GrOverlay | null;
    }
    return this._overlays.confirmDelete;
  }

  get confirmDiscardOverlay() {
    if (!this._overlays.confirmDiscard) {
      this._enableOverlay = true;
      flush();
      this._overlays.confirmDiscard = this.shadowRoot?.querySelector(
        '#confirmDiscardOverlay'
      ) as GrOverlay | null;
    }
    return this._overlays.confirmDiscard;
  }

  _computeShowHideIcon(collapsed: boolean) {
    return collapsed ? 'gr-icons:expand-more' : 'gr-icons:expand-less';
  }

  _computeShowHideAriaLabel(collapsed: boolean) {
    return collapsed ? 'Expand' : 'Collapse';
  }

  @observe('showActions', 'isRobotComment')
  _calculateActionstoShow(showActions?: boolean, isRobotComment?: boolean) {
    // Polymer 2: check for undefined
    if ([showActions, isRobotComment].includes(undefined)) {
      return;
    }

    this._showHumanActions = showActions && !isRobotComment;
    this._showRobotActions = showActions && isRobotComment;
  }

  @observe('comment')
  _isRobotComment(comment: UIRobot) {
    this.isRobotComment = !!comment.robot_id;
  }

  isOnParent() {
    return this.side === 'PARENT';
  }

  _getIsAdmin() {
    return this.$.restAPI.getIsAdmin();
  }

  _computeDraftTooltip(unableToSave: boolean) {
    return unableToSave
      ? 'Unable to save draft. Please try to save again.'
      : "This draft is only visible to you. To publish drafts, click the 'Reply'" +
          "or 'Start review' button at the top of the change or press the 'A' key.";
  }

  _computeDraftText(unableToSave: boolean) {
    return 'DRAFT' + (unableToSave ? '(Failed to save)' : '');
  }

  save(opt_comment?: UIComment) {
    let comment = opt_comment;
    if (!comment) {
      comment = this.comment;
    }

    this.set('comment.message', this._messageText);
    this.editing = false;
    this.disabled = true;

    if (!this._messageText) {
      return this._discardDraft();
    }

    this._xhrPromise = this._saveDraft(comment)
      .then(response => {
        this.disabled = false;
        if (!response.ok) {
          return;
        }

        this._eraseDraftComment();
        return this.$.restAPI.getResponseObject(response).then(obj => {
          const resComment = (obj as unknown) as UIDraft;
          if (!isDraft(this.comment)) throw new Error('Can only save drafts.');
          resComment.__draft = true;
          // Maintain the ephemeral draft ID for identification by other
          // elements.
          if (this.comment?.__draftID) {
            resComment.__draftID = this.comment.__draftID;
          }
          resComment.__commentSide = this.commentSide;
          this.comment = resComment;
          this._fireSave();
          return obj;
        });
      })
      .catch(err => {
        this.disabled = false;
        throw err;
      });

    return this._xhrPromise;
  }

  _eraseDraftComment() {
    // Prevents a race condition in which removing the draft comment occurs
    // prior to it being saved.
    this.cancelDebouncer('store');

    if (!this.comment?.path) throw new Error('Cannot erase Draft Comment');
    if (this.changeNum === undefined) {
      throw new Error('undefined changeNum');
    }
    this.$.storage.eraseDraftComment({
      changeNum: this.changeNum,
      patchNum: this._getPatchNum(),
      path: this.comment.path,
      line: this.comment.line,
      range: this.comment.range,
    });
  }

  _commentChanged(comment: UIComment) {
    this.editing = !!comment.__editing;
    this.resolved = !comment.unresolved;
    if (this.editing) {
      // It's a new draft/reply, notify.
      this._fireUpdate();
    }
  }

  @observe('comment', 'comments.*')
  _computeHasHumanReply() {
    const comment = this.comment;
    if (!comment || !this.comments) return;
    // hide please fix button for robot comment that has human reply
    this._hasHumanReply = this.comments.some(
      c =>
        c.in_reply_to &&
        c.in_reply_to === comment.id &&
        !(c as UIRobot).robot_id
    );
  }

  _getEventPayload(): CommentEventDetail {
    return {comment: this.comment, patchNum: this.patchNum};
  }

  _fireSave() {
    this.dispatchEvent(
      new CustomEvent('comment-save', {
        detail: this._getEventPayload(),
        composed: true,
        bubbles: true,
      })
    );
  }

  _fireUpdate() {
    this.debounce('fire-update', () => {
      this.dispatchEvent(
        new CustomEvent('comment-update', {
          detail: this._getEventPayload(),
          composed: true,
          bubbles: true,
        })
      );
    });
  }

  _computeAccountLabelClass(draft: boolean) {
    return draft ? 'draft' : '';
  }

  _draftChanged(draft: boolean) {
    this.$.container.classList.toggle('draft', draft);
  }

  _editingChanged(editing?: boolean, previousValue?: boolean) {
    // Polymer 2: observer fires when at least one property is defined.
    // Do nothing to prevent comment.__editing being overwritten
    // if previousValue is undefined
    if (previousValue === undefined) return;

    this.$.container.classList.toggle('editing', editing);
    if (this.comment && this.comment.id) {
      const cancelButton = this.shadowRoot?.querySelector(
        '.cancel'
      ) as GrButton | null;
      if (cancelButton) {
        cancelButton.hidden = !editing;
      }
    }
    if (this.comment) {
      this.comment.__editing = this.editing;
    }
    if (!!editing !== !!previousValue) {
      // To prevent event firing on comment creation.
      this._fireUpdate();
    }
    if (editing) {
      this.async(() => {
        flush();
        this.textarea && this.textarea.putCursorAtEnd();
      }, 1);
    }
  }

  _computeDeleteButtonClass(isAdmin: boolean, draft: boolean) {
    return isAdmin && !draft ? 'showDeleteButtons' : '';
  }

  _computeSaveDisabled(
    draft: string,
    comment: UIComment | undefined,
    resolved?: boolean
  ) {
    // If resolved state has changed and a msg exists, save should be enabled.
    if (!comment || (comment.unresolved === resolved && draft)) {
      return false;
    }
    return !draft || draft.trim() === '';
  }

  _handleSaveKey(e: Event) {
    if (
      !this._computeSaveDisabled(this._messageText, this.comment, this.resolved)
    ) {
      e.preventDefault();
      this._handleSave(e);
    }
  }

  _handleEsc(e: Event) {
    if (!this._messageText.length) {
      e.preventDefault();
      this._handleCancel(e);
    }
  }

  _handleToggleCollapsed() {
    this.collapsed = !this.collapsed;
  }

  _toggleCollapseClass(collapsed: boolean) {
    if (collapsed) {
      this.$.container.classList.add('collapsed');
    } else {
      this.$.container.classList.remove('collapsed');
    }
  }

  @observe('comment.message')
  _commentMessageChanged(message: string) {
    this._messageText = message || '';
  }

  _messageTextChanged(_: string, oldValue: string) {
    if (!this.comment || (this.comment && this.comment.id)) {
      return;
    }

    const patchNum = this.comment.patch_set
      ? this.comment.patch_set
      : this._getPatchNum();
    const {path, line, range} = this.comment;
    if (path) {
      this.debounce(
        'store',
        () => {
          const message = this._messageText;
          if (this.changeNum === undefined) {
            throw new Error('undefined changeNum');
          }
          const commentLocation: StorageLocation = {
            changeNum: this.changeNum,
            patchNum,
            path,
            line,
            range,
          };

          if ((!message || !message.length) && oldValue) {
            // If the draft has been modified to be empty, then erase the storage
            // entry.
            this.$.storage.eraseDraftComment(commentLocation);
          } else {
            this.$.storage.setDraftComment(commentLocation, message);
          }
        },
        STORAGE_DEBOUNCE_INTERVAL
      );
    }
  }

  _handleAnchorClick(e: Event) {
    e.preventDefault();
    if (!this.comment) return;
    this.dispatchEvent(
      new CustomEvent('comment-anchor-tap', {
        bubbles: true,
        composed: true,
        detail: {
          number: this.comment.line || FILE,
          side: this.side,
        },
      })
    );
  }

  _handleEdit(e: Event) {
    e.preventDefault();
    if (this.comment?.message) this._messageText = this.comment.message;
    this.editing = true;
    this.reporting.recordDraftInteraction();
  }

  _handleSave(e: Event) {
    e.preventDefault();

    // Ignore saves started while already saving.
    if (this.disabled) {
      return;
    }
    const timingLabel = this.comment?.id
      ? REPORT_UPDATE_DRAFT
      : REPORT_CREATE_DRAFT;
    const timer = this.reporting.getTimer(timingLabel);
    this.set('comment.__editing', false);
    return this.save().then(() => {
      timer.end();
    });
  }

  _handleCancel(e: Event) {
    e.preventDefault();

    if (
      !this.comment?.message ||
      this.comment.message.trim().length === 0 ||
      !this.comment.id
    ) {
      this._fireDiscard();
      return;
    }
    this._messageText = this.comment.message;
    this.editing = false;
  }

  _fireDiscard() {
    this.cancelDebouncer('fire-update');
    this.dispatchEvent(
      new CustomEvent('comment-discard', {
        detail: this._getEventPayload(),
        composed: true,
        bubbles: true,
      })
    );
  }

  _handleFix() {
    this.dispatchEvent(
      new CustomEvent('create-fix-comment', {
        bubbles: true,
        composed: true,
        detail: this._getEventPayload(),
      })
    );
  }

  _handleShowFix() {
    this.dispatchEvent(
      new CustomEvent('open-fix-preview', {
        bubbles: true,
        composed: true,
        detail: this._getEventPayload(),
      })
    );
  }

  _hasNoFix(comment: UIComment) {
    return !comment || !(comment as UIRobot).fix_suggestions;
  }

  _handleDiscard(e: Event) {
    e.preventDefault();
    this.reporting.recordDraftInteraction();

    if (!this._messageText) {
      this._discardDraft();
      return;
    }

    this._openOverlay(this.confirmDiscardOverlay).then(() => {
      const dialog = this.confirmDiscardOverlay?.querySelector(
        '#confirmDiscardDialog'
      ) as GrDialog | null;
      if (dialog) dialog.resetFocus();
    });
  }

  _handleConfirmDiscard(e: Event) {
    e.preventDefault();
    const timer = this.reporting.getTimer(REPORT_DISCARD_DRAFT);
    this._closeConfirmDiscardOverlay();
    return this._discardDraft().then(() => {
      timer.end();
    });
  }

  _discardDraft() {
    if (!this.comment) return Promise.reject(new Error('undefined comment'));
    if (!isDraft(this.comment)) {
      return Promise.reject(new Error('Cannot discard a non-draft comment.'));
    }
    this.discarding = true;
    this.editing = false;
    this.disabled = true;
    this._eraseDraftComment();

    if (!this.comment.id) {
      this.disabled = false;
      this._fireDiscard();
      return Promise.resolve();
    }

    this._xhrPromise = this._deleteDraft(this.comment)
      .then(response => {
        this.disabled = false;
        if (!response.ok) {
          this.discarding = false;
        }

        this._fireDiscard();
        return response;
      })
      .catch(err => {
        this.disabled = false;
        throw err;
      });

    return this._xhrPromise;
  }

  _closeConfirmDiscardOverlay() {
    this._closeOverlay(this.confirmDiscardOverlay);
  }

  _getSavingMessage(numPending: number, requestFailed?: boolean) {
    if (requestFailed) {
      return UNSAVED_MESSAGE;
    }
    if (numPending === 0) {
      return SAVED_MESSAGE;
    }
    return [
      SAVING_MESSAGE,
      numPending,
      numPending === 1 ? DRAFT_SINGULAR : DRAFT_PLURAL,
    ].join(' ');
  }

  _showStartRequest() {
    const numPending = ++this._numPendingDraftRequests.number;
    this._updateRequestToast(numPending);
  }

  _showEndRequest() {
    const numPending = --this._numPendingDraftRequests.number;
    this._updateRequestToast(numPending);
  }

  _handleFailedDraftRequest() {
    this._numPendingDraftRequests.number--;

    // Cancel the debouncer so that error toasts from the error-manager will
    // not be overridden.
    this.cancelDebouncer('draft-toast');
    this._updateRequestToast(
      this._numPendingDraftRequests.number,
      /* requestFailed=*/ true
    );
  }

  _updateRequestToast(numPending: number, requestFailed?: boolean) {
    const message = this._getSavingMessage(numPending, requestFailed);
    this.debounce(
      'draft-toast',
      () => {
        // Note: the event is fired on the body rather than this element because
        // this element may not be attached by the time this executes, in which
        // case the event would not bubble.
        document.body.dispatchEvent(
          new CustomEvent('show-alert', {
            detail: {message},
            bubbles: true,
            composed: true,
          })
        );
      },
      TOAST_DEBOUNCE_INTERVAL
    );
  }

  _handleDraftFailure() {
    this.$.container.classList.add('unableToSave');
    this._unableToSave = true;
    this._handleFailedDraftRequest();
  }

  _saveDraft(draft?: UIComment) {
    if (!draft || this.changeNum === undefined || this.patchNum === undefined) {
      throw new Error('undefined draft or changeNum or patchNum');
    }
    this._showStartRequest();
    return this.$.restAPI
      .saveDiffDraft(this.changeNum, this.patchNum, draft)
      .then(result => {
        if (result.ok) {
          // remove
          this._unableToSave = false;
          this.$.container.classList.remove('unableToSave');
          this._showEndRequest();
        } else {
          this._handleDraftFailure();
        }
        return result;
      })
      .catch(err => {
        this._handleDraftFailure();
        throw err;
      });
  }

  _deleteDraft(draft: UIComment) {
    if (this.changeNum === undefined || this.patchNum === undefined) {
      throw new Error('undefined changeNum or patchNum');
    }
    this._showStartRequest();
    if (!draft.id) throw new Error('Missing id in comment draft.');
    return this.$.restAPI
      .deleteDiffDraft(this.changeNum, this.patchNum, {id: draft.id})
      .then(result => {
        if (result.ok) {
          this._showEndRequest();
        } else {
          this._handleFailedDraftRequest();
        }
        return result;
      });
  }

  _getPatchNum(): PatchSetNum {
    const patchNum = this.isOnParent()
      ? ('PARENT' as PatchSetNum)
      : this.patchNum;
    if (patchNum === undefined) throw new Error('patchNum undefined');
    return patchNum;
  }

  @observe('changeNum', 'patchNum', 'comment')
  _loadLocalDraft(
    changeNum: number,
    patchNum?: PatchSetNum,
    comment?: UIComment
  ) {
    // Polymer 2: check for undefined
    if ([changeNum, patchNum, comment].includes(undefined)) {
      return;
    }

    // Only apply local drafts to comments that haven't been saved
    // remotely, and haven't been given a default message already.
    //
    // Don't get local draft if there is another comment that is currently
    // in an editing state.
    if (
      !comment ||
      comment.id ||
      comment.message ||
      comment.__otherEditing ||
      !comment.path
    ) {
      if (comment) delete comment.__otherEditing;
      return;
    }

    const draft = this.$.storage.getDraftComment({
      changeNum,
      patchNum: this._getPatchNum(),
      path: comment.path,
      line: comment.line,
      range: comment.range,
    });

    if (draft) {
      this.set('comment.message', draft.message);
    }
  }

  _handleToggleResolved() {
    this.reporting.recordDraftInteraction();
    this.resolved = !this.resolved;
    // Modify payload instead of this.comment, as this.comment is passed from
    // the parent by ref.
    const payload = this._getEventPayload();
    if (!payload.comment) {
      throw new Error('comment not defined in payload');
    }
    payload.comment.unresolved = !this.$.resolvedCheckbox.checked;
    this.dispatchEvent(
      new CustomEvent('comment-update', {
        detail: payload,
        composed: true,
        bubbles: true,
      })
    );
    if (!this.editing) {
      // Save the resolved state immediately.
      this.save(payload.comment);
    }
  }

  _handleCommentDelete() {
    this._openOverlay(this.confirmDeleteOverlay);
  }

  _handleCancelDeleteComment() {
    this._closeOverlay(this.confirmDeleteOverlay);
  }

  _openOverlay(overlay?: GrOverlay | null) {
    if (!overlay) {
      return Promise.reject(new Error('undefined overlay'));
    }
    getRootElement().appendChild(overlay);
    return overlay.open();
  }

  _computeHideRunDetails(comment: UIRobot, collapsed: boolean) {
    if (!comment) return true;
    return !(comment.robot_id && comment.url && !collapsed);
  }

  _closeOverlay(overlay?: GrOverlay | null) {
    if (overlay) {
      getRootElement().removeChild(overlay);
      overlay.close();
    }
  }

  _handleConfirmDeleteComment() {
    const dialog = this.confirmDeleteOverlay?.querySelector(
      '#confirmDeleteComment'
    ) as GrConfirmDeleteCommentDialog | null;
    if (!dialog || !dialog.message) {
      throw new Error('missing confirm delete dialog');
    }
    if (
      !this.comment ||
      !this.comment.id ||
      this.changeNum === undefined ||
      this.patchNum === undefined
    ) {
      throw new Error('undefined comment or id or changeNum or patchNum');
    }
    this.$.restAPI
      .deleteComment(
        this.changeNum,
        this.patchNum,
        this.comment.id,
        dialog.message
      )
      .then(newComment => {
        this._handleCancelDeleteComment();
        this.comment = newComment;
      });
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-comment': GrComment;
  }
}
