/**
 * @license
 * Copyright 2015 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../shared/gr-dropdown-list/gr-dropdown-list';
import '../../shared/gr-select/gr-select';
import '../../shared/gr-weblink/gr-weblink';
import {convertToString, pluralize} from '../../../utils/string-util';
import {getAppContext} from '../../../services/app-context';
import {
  computeLatestPatchNum,
  findSortedIndex,
  getParentIndex,
  getRevisionByPatchNum,
  isMergeParent,
  PatchSet,
  convertToPatchSetNum,
  getParentInfoString,
  shorten,
} from '../../../utils/patch-set-util';
import {ReportingService} from '../../../services/gr-reporting/gr-reporting';
import {
  BasePatchSetNum,
  EDIT,
  NumericChangeId,
  PARENT,
  PatchSetNum,
  RevisionInfo,
  RevisionPatchSetNum,
  Timestamp,
  WebLinkInfo,
} from '../../../types/common';
import {RevisionInfo as RevisionInfoClass} from '../../shared/revision-info/revision-info';
import {ChangeComments} from '../gr-comment-api/gr-comment-api';
import {
  DropdownItem,
  GrDropdownList,
} from '../../shared/gr-dropdown-list/gr-dropdown-list';
import {EditRevisionInfo} from '../../../types/types';
import {a11yStyles} from '../../../styles/gr-a11y-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {LitElement, css, html, nothing} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {subscribe} from '../../lit/subscription-controller';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {resolve} from '../../../models/dependency';
import {ValueChangedEvent} from '../../../types/events';
import {changeModelToken} from '../../../models/change/change-model';
import {changeViewModelToken} from '../../../models/views/change';
import {fireNoBubbleNoCompose} from '../../../utils/event-util';
import {FlagsService, KnownExperimentId} from '../../../services/flags/flags';

// Maximum length for patch set descriptions.
const PATCH_DESC_MAX_LENGTH = 500;

export interface PatchRangeChangeDetail {
  patchNum?: RevisionPatchSetNum;
  basePatchNum?: BasePatchSetNum;
}

export type PatchRangeChangeEvent = CustomEvent<PatchRangeChangeDetail>;

export interface FilesWebLinks {
  meta_a: WebLinkInfo[];
  meta_b: WebLinkInfo[];
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-patch-range-select': GrPatchRangeSelect;
  }
}

declare global {
  interface HTMLElementEventMap {
    'patch-range-change': PatchRangeChangeEvent;
  }
}

/**
 * Fired when the patch range changes
 *
 * @event patch-range-change
 *
 * @property {string} patchNum
 * @property {string} basePatchNum
 */
@customElement('gr-patch-range-select')
export class GrPatchRangeSelect extends LitElement {
  @query('#patchNumDropdown')
  patchNumDropdown?: GrDropdownList;

  @state()
  availablePatches: PatchSet[] = [];

  @state()
  changeNum?: NumericChangeId;

  @property({type: Object})
  filesWeblinks?: FilesWebLinks;

  @state()
  patchNum?: RevisionPatchSetNum;

  @state()
  basePatchNum?: BasePatchSetNum;

  @state()
  revisionInfo?: RevisionInfoClass;

  @state()
  sortedRevisions: (RevisionInfo | EditRevisionInfo)[] = [];

  @state()
  changeComments?: ChangeComments;

  private readonly reporting: ReportingService =
    getAppContext().reportingService;

  private readonly flags: FlagsService = getAppContext().flagsService;

  private readonly getCommentsModel = resolve(this, commentsModelToken);

  private readonly getChangeModel = resolve(this, changeModelToken);

  private readonly getViewModel = resolve(this, changeViewModelToken);

  constructor() {
    super();
    subscribe(
      this,
      () => this.getViewModel().changeNum$,
      x => (this.changeNum = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().change$,
      x => (this.revisionInfo = x ? new RevisionInfoClass(x) : undefined)
    );
    subscribe(
      this,
      () => this.getChangeModel().patchNum$,
      x => (this.patchNum = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().basePatchNum$,
      x => (this.basePatchNum = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().patchsets$,
      x => (this.availablePatches = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().revisions$,
      x => (this.sortedRevisions = x)
    );
    subscribe(
      this,
      () => this.getCommentsModel().changeComments$,
      x => (this.changeComments = x)
    );
  }

  static override get styles() {
    return [
      a11yStyles,
      sharedStyles,
      css`
        :host {
          align-items: center;
          display: flex;
        }
        select {
          max-width: 15em;
        }
        .arrow {
          color: var(--deemphasized-text-color);
          margin: 0 var(--spacing-m);
        }
        gr-dropdown-list {
          --trigger-style-text-color: var(--deemphasized-text-color);
          --trigger-style-font-family: var(--font-family);
        }
        .filesWeblinks gr-weblink {
          vertical-align: baseline;
        }
        @media screen and (max-width: 50em) {
          .filesWeblinks {
            display: none;
          }
          /* prettier formatter removes semi-colons after css mixins. */
          /* prettier-ignore */
          gr-dropdown-list {
            --native-select-style: {
              max-width: 5.25em;
            };
          }
        }
      `,
    ];
  }

  override render() {
    if (!this.changeNum || !this.patchNum || !this.basePatchNum) {
      return nothing;
    }
    return html`
      <h3 class="assistive-tech-only">Patchset Range Selection</h3>
      <span class="patchRange" aria-label="patch range starts with">
        <gr-dropdown-list
          id="basePatchDropdown"
          .value=${convertToString(this.basePatchNum)}
          .items=${this.computeBaseDropdownContent()}
          @value-change=${this.handlePatchChange}
        >
        </gr-dropdown-list>
      </span>
      ${this.renderWeblinks(this.filesWeblinks?.meta_a)}
      <span aria-hidden="true" class="arrow">→</span>
      <span class="patchRange" aria-label="patch range ends with">
        <gr-dropdown-list
          id="patchNumDropdown"
          .value=${convertToString(this.patchNum)}
          .items=${this.computePatchDropdownContent()}
          @value-change=${this.handlePatchChange}
        >
        </gr-dropdown-list>
        ${this.renderWeblinks(this.filesWeblinks?.meta_b)}
      </span>
    `;
  }

  private renderWeblinks(fileLinks?: WebLinkInfo[]) {
    if (!fileLinks) return;
    return html`<span class="filesWeblinks">
      ${fileLinks.map(
        weblink => html`<gr-weblink .info=${weblink}></gr-weblink>`
      )}</span
    > `;
  }

  // Private method, but visible for testing.
  computeBaseDropdownContent(): DropdownItem[] {
    if (
      this.patchNum === undefined ||
      this.changeComments === undefined ||
      this.revisionInfo === undefined
    ) {
      return [];
    }

    const maxParents = this.revisionInfo.getMaxParents();
    const isMerge = this.revisionInfo.isMergeCommit(this.patchNum);
    const parentCount = this.revisionInfo.getParentCount(this.patchNum);
    const rev = getRevisionByPatchNum(this.sortedRevisions, this.patchNum);

    const dropdownContent: DropdownItem[] = [];
    for (const basePatch of this.availablePatches) {
      const basePatchNum = basePatch.num;
      const entry: DropdownItem = this.createDropdownEntry(
        basePatchNum,
        'Patchset ',
        shorten(basePatch.sha)!
      );
      dropdownContent.push({
        ...entry,
        disabled: this.computeLeftDisabled(basePatch.num, this.patchNum),
      });
    }

    const showParentsData = this.flags.isEnabled(
      KnownExperimentId.REVISION_PARENTS_DATA
    );
    dropdownContent.push({
      text: isMerge ? 'Auto Merge' : 'Base',
      bottomText:
        showParentsData && !isMerge ? getParentInfoString(rev, 0) : undefined,
      value: PARENT,
    });

    for (let idx = 0; isMerge && idx < maxParents; idx++) {
      dropdownContent.push({
        disabled: idx >= parentCount,
        triggerText: `Parent ${idx + 1}`,
        text: `Parent ${idx + 1}`,
        bottomText: showParentsData ? getParentInfoString(rev, idx) : undefined,
        mobileText: `Parent ${idx + 1}`,
        value: -(idx + 1),
      });
    }

    return dropdownContent;
  }

  private computeMobileText(patchNum: PatchSetNum) {
    return (
      `${patchNum}` +
      `${this.computePatchSetCommentsString(patchNum)}` +
      `${this.computePatchSetDescription(patchNum, true)}`
    );
  }

  // Private method, but visible for testing.
  computePatchDropdownContent(): DropdownItem[] {
    if (
      this.availablePatches === undefined ||
      this.basePatchNum === undefined ||
      this.changeComments === undefined
    ) {
      return [];
    }

    const dropdownContent: DropdownItem[] = [];
    for (const patch of this.availablePatches) {
      const patchNum = patch.num;
      const entry = this.createDropdownEntry(
        patchNum,
        patchNum === EDIT ? '' : 'Patchset ',
        shorten(patch.sha)!
      );
      dropdownContent.push({
        ...entry,
        disabled: this.computeRightDisabled(this.basePatchNum, patchNum),
      });
    }
    return dropdownContent;
  }

  private computeText(patchNum: PatchSetNum, prefix: string, sha: string) {
    return `${prefix}${patchNum} | ${sha}`;
  }

  private createDropdownEntry(
    patchNum: PatchSetNum,
    prefix: string,
    sha: string
  ) {
    const entry: DropdownItem = {
      triggerText: `${prefix}${patchNum}`,
      text: this.computeText(patchNum, prefix, sha),
      mobileText: this.computeMobileText(patchNum),
      bottomText: `${this.computePatchSetDescription(patchNum)}`,
      value: patchNum,
      commentThreads: this.changeComments?.computeCommentThreads(
        {
          patchNum,
        },
        true
      ),
    };
    const date = this.computePatchSetDate(patchNum);
    if (date) {
      entry.date = date;
    }
    return entry;
  }

  /**
   * The basePatchNum should always be <= patchNum -- because sortedRevisions
   * is sorted in reverse order (higher patchset nums first), invalid base
   * patch nums have an index greater than the index of patchNum.
   *
   * Private method, but visible for testing.
   *
   * @param basePatchNum The possible base patch num.
   * @param patchNum The current selected patch num.
   */
  computeLeftDisabled(
    basePatchNum: PatchSetNum,
    patchNum: PatchSetNum
  ): boolean {
    return (
      findSortedIndex(basePatchNum, this.sortedRevisions) <=
      findSortedIndex(patchNum, this.sortedRevisions)
    );
  }

  /**
   * The basePatchNum should always be <= patchNum -- because sortedRevisions
   * is sorted in reverse order (higher patchset nums first), invalid patch
   * nums have an index greater than the index of basePatchNum.
   *
   * In addition, if the current basePatchNum is PARENT, all patchNums are
   * valid.
   *
   * If the current basePatchNum is a parent index, then only patches that have
   * at least that many parents are valid.
   *
   * Private method, but visible for testing.
   *
   * @param basePatchNum The current selected base patch num.
   * @param patchNum The possible patch num.
   */
  computeRightDisabled(
    basePatchNum: BasePatchSetNum,
    patchNum: RevisionPatchSetNum
  ): boolean {
    if (basePatchNum === PARENT) {
      return false;
    }

    if (isMergeParent(basePatchNum)) {
      if (!this.revisionInfo) {
        return true;
      }
      // Note: parent indices use 1-offset.
      return (
        this.revisionInfo.getParentCount(patchNum) <
        getParentIndex(basePatchNum)
      );
    }

    return (
      findSortedIndex(basePatchNum, this.sortedRevisions) <=
      findSortedIndex(patchNum, this.sortedRevisions)
    );
  }

  // TODO(dhruvsri): have ported comments contribute to this count
  // Private method, but visible for testing.
  computePatchSetCommentsString(patchNum: PatchSetNum): string {
    if (!this.changeComments) return '';

    const commentThreadCount = this.changeComments.computeCommentThreads(
      {
        patchNum,
      },
      true
    ).length;
    const commentThreadString = pluralize(commentThreadCount, 'comment');

    const unresolvedCount = this.changeComments.computeUnresolvedNum(
      {patchNum},
      true
    );
    const unresolvedString =
      unresolvedCount === 0 ? '' : `${unresolvedCount} unresolved`;

    if (!commentThreadString.length && !unresolvedString.length) {
      return '';
    }

    return (
      ` (${commentThreadString}` +
      // Add a comma + space if both comment threads and unresolved
      (commentThreadString && unresolvedString ? ', ' : '') +
      `${unresolvedString})`
    );
  }

  private computePatchSetDescription(
    patchNum: PatchSetNum,
    addFrontSpace?: boolean
  ) {
    const rev = getRevisionByPatchNum(this.sortedRevisions, patchNum);
    return rev?.description
      ? (addFrontSpace ? ' ' : '') +
          rev.description.substring(0, PATCH_DESC_MAX_LENGTH)
      : '';
  }

  private computePatchSetDate(patchNum: PatchSetNum): Timestamp | undefined {
    const rev = getRevisionByPatchNum(this.sortedRevisions, patchNum);
    return rev ? rev.created : undefined;
  }

  /**
   * Catches value-change events from the patchset dropdowns and determines
   * whether or not a patch change event should be fired.
   */
  private handlePatchChange(e: ValueChangedEvent<string>) {
    const detail: PatchRangeChangeDetail = {
      patchNum: this.patchNum,
      basePatchNum: this.basePatchNum,
    };
    const target = e.target;
    const patchSetValue = convertToPatchSetNum(
      e.detail.value
    ) as RevisionPatchSetNum;
    const latestPatchNum = computeLatestPatchNum(this.availablePatches);
    if (target === this.patchNumDropdown) {
      if (detail.patchNum === patchSetValue) return;
      this.reporting.reportInteraction('right-patchset-changed', {
        previous: detail.patchNum,
        current: patchSetValue,
        latest: latestPatchNum,
        commentCount: this.changeComments?.computeCommentThreads({
          patchNum: patchSetValue,
        }).length,
      });
      detail.patchNum = patchSetValue;
    } else {
      if (detail.basePatchNum === patchSetValue) return;
      this.reporting.reportInteraction('left-patchset-changed', {
        previous: detail.basePatchNum,
        current: patchSetValue,
        commentCount: this.changeComments?.computeCommentThreads({
          patchNum: patchSetValue,
        }).length,
      });
      detail.basePatchNum = patchSetValue as BasePatchSetNum;
    }

    fireNoBubbleNoCompose(this, 'patch-range-change', detail);
  }
}
