/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {Subscription} from 'rxjs';
import {AbortStop, CursorMoveResult, Stop} from '../../../api/core';
import {
  DiffViewMode,
  FileRangeSelection,
  GrDiffCursor as GrDiffCursorApi,
  GrDiffLineType,
  LineNumber,
  LineSelectedEventDetail,
} from '../../../api/diff';
import {ScrollMode, Side} from '../../../constants/constants';
import {
  GrCursorManager,
  isTargetable,
} from '../../../elements/shared/gr-cursor-manager/gr-cursor-manager';
import {GrDiff} from '../gr-diff/gr-diff';
import {fire} from '../../../utils/event-util';
import {GrDiffRow} from '../gr-diff-builder/gr-diff-row';

const LEFT_SIDE_CLASS = 'target-side-left';
const RIGHT_SIDE_CLASS = 'target-side-right';

/**
 * From <tr> diff row go up to <tbody> diff chunk.
 *
 * In Lit based diff there is a <gr-diff-row> element in between the two.
 */
export function fromRowToChunk(
  rowEl: HTMLElement
): HTMLTableSectionElement | undefined {
  const parent = rowEl.parentElement;
  if (!parent) return undefined;
  if (parent.tagName === 'TBODY') {
    return parent as HTMLTableSectionElement;
  }

  const grandParent = parent.parentElement;
  if (!grandParent) return undefined;
  if (grandParent.tagName === 'TBODY') {
    return grandParent as HTMLTableSectionElement;
  }

  return undefined;
}

/** A subset of the GrDiff API that the cursor is using. */
export interface GrDiffCursorable extends HTMLElement {
  isRangeSelected(): boolean;
  getSelectedRange(): FileRangeSelection | undefined;
  createRangeComment(): void;
  getCursorStops(): Stop[];
  path?: string;
}

export class GrDiffCursor implements GrDiffCursorApi {
  private preventAutoScrollOnManualScroll = false;

  set side(side: Side) {
    if (this.sideInternal === side) {
      return;
    }
    if (this.diffRowTR) {
      this.fireCursorMoved('line-cursor-moved-out');
    }
    this.sideInternal = side;
    this.updateSideClass();
    if (this.diffRowTR) {
      this.fireCursorMoved('line-cursor-moved-in');
    }
  }

  get side(): Side {
    return this.sideInternal;
  }

  private sideInternal = Side.RIGHT;

  set diffRowTR(diffRowTR: HTMLTableRowElement | undefined) {
    if (this.diffRowTRInternal) {
      this.diffRowTRInternal.classList.remove(
        LEFT_SIDE_CLASS,
        RIGHT_SIDE_CLASS
      );
      this.fireCursorMoved('line-cursor-moved-out');
    }
    this.diffRowTRInternal = diffRowTR;

    this.updateSideClass();
    if (this.diffRowTR) {
      this.fireCursorMoved('line-cursor-moved-in');
    }
  }

  /**
   * This is the current target of the diff cursor.
   */
  get diffRowTR(): HTMLTableRowElement | undefined {
    return this.diffRowTRInternal;
  }

  private diffRowTRInternal?: HTMLTableRowElement;

  private diffs: GrDiffCursorable[] = [];

  /**
   * If set, the cursor will attempt to move to the line number (instead of
   * the first chunk) the next time the diff renders. It is set back to null
   * when used. It should be only used if you want the line to be focused
   * after initialization of the component and page should scroll
   * to that position. This parameter should be set at most for one gr-diff
   * element in the page.
   */
  initialLineNumber: number | null = null;

  // visible for testing
  cursorManager = new GrCursorManager();

  private targetSubscription?: Subscription;

  constructor() {
    this.cursorManager.cursorTargetClass = 'target-row';
    this.cursorManager.scrollMode = ScrollMode.KEEP_VISIBLE;
    this.cursorManager.focusOnMove = true;

    window.addEventListener('scroll', this.boundHandleWindowScroll);
    this.targetSubscription = this.cursorManager.target$.subscribe(target => {
      this.diffRowTR = (target ?? undefined) as HTMLTableRowElement | undefined;
    });
  }

  dispose() {
    this.cursorManager.unsetCursor();
    if (this.targetSubscription) this.targetSubscription.unsubscribe();
    window.removeEventListener('scroll', this.boundHandleWindowScroll);
  }

  // Don't remove - used by clients embedding gr-diff outside of Gerrit.
  isAtStart() {
    return this.cursorManager.isAtStart();
  }

  // Don't remove - used by clients embedding gr-diff outside of Gerrit.
  isAtEnd() {
    return this.cursorManager.isAtEnd();
  }

  moveLeft() {
    this.side = Side.LEFT;
    if (this.isTargetBlank()) {
      this.moveUp();
    }
  }

  moveRight() {
    this.side = Side.RIGHT;
    if (this.isTargetBlank()) {
      this.moveUp();
    }
  }

  moveDown() {
    if (this.getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
      return this.cursorManager.next({
        filter: (row: Element) => this.rowHasSide(row),
      });
    } else {
      return this.cursorManager.next();
    }
  }

  moveUp() {
    if (this.getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
      return this.cursorManager.previous({
        filter: (row: Element) => this.rowHasSide(row),
      });
    } else {
      return this.cursorManager.previous();
    }
  }

  moveToVisibleArea() {
    if (this.getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
      this.cursorManager.moveToVisibleArea((row: Element) =>
        this.rowHasSide(row)
      );
    } else {
      this.cursorManager.moveToVisibleArea();
    }
  }

  moveToNextChunk(clipToTop?: boolean): CursorMoveResult {
    const result = this.cursorManager.next({
      filter: (row: HTMLElement) => this.isFirstRowOfChunk(row),
      getTargetHeight: target => fromRowToChunk(target)?.scrollHeight || 0,
      clipToTop,
    });
    this.fixSide();
    return result;
  }

  moveToPreviousChunk(): CursorMoveResult {
    const result = this.cursorManager.previous({
      filter: (row: HTMLElement) => this.isFirstRowOfChunk(row),
    });
    this.fixSide();
    return result;
  }

  moveToNextCommentThread(): CursorMoveResult {
    if (this.isAtEnd()) {
      return CursorMoveResult.CLIPPED;
    }
    const result = this.cursorManager.next({
      filter: (row: HTMLElement) => this.rowHasThread(row),
    });
    this.fixSide();
    return result;
  }

  moveToPreviousCommentThread(): CursorMoveResult {
    const result = this.cursorManager.previous({
      filter: (row: HTMLElement) => this.rowHasThread(row),
    });
    this.fixSide();
    return result;
  }

  moveToLineNumber(
    number: LineNumber,
    side: Side,
    path?: string,
    intentionalMove?: boolean
  ) {
    const row = this.findRowByNumberAndFile(number, side, path);
    if (row) {
      this.side = side;
      this.cursorManager.setCursor(row, undefined, intentionalMove);
    }
  }

  /**
   * The target of the diff cursor is always a <tr> element. That is the first
   * direct child of a <gr-diff-row> element. We typically want to retrieve
   * the `GrDiffRow`, because it supplies methods that we can use without
   * making further assumptions about the internal DOM structure.
   */
  getTargetDiffRow(): GrDiffRow | undefined {
    let el: HTMLElement | undefined = this.diffRowTR;
    while (el) {
      if (el.tagName === 'GR-DIFF-ROW') return el as GrDiffRow;
      el = el.parentElement ?? undefined;
    }
    return undefined;
  }

  getTargetLineNumber(): LineNumber | undefined {
    const diffRow = this.getTargetDiffRow();
    return diffRow?.lineNumber(this.side);
  }

  getTargetDiffElement(): GrDiff | undefined {
    if (!this.diffRowTR) return undefined;

    const hostOwner = this.diffRowTR.getRootNode() as ShadowRoot;
    if (hostOwner?.host?.tagName === 'GR-DIFF') {
      return hostOwner.host as GrDiff;
    }
    return undefined;
  }

  moveToFirstChunk() {
    this.cursorManager.moveToStart();
    if (this.diffRowTR && !this.isFirstRowOfChunk(this.diffRowTR)) {
      this.moveToNextChunk(true);
    } else {
      this.fixSide();
    }
  }

  moveToLastChunk() {
    this.cursorManager.moveToEnd();
    if (this.diffRowTR && !this.isFirstRowOfChunk(this.diffRowTR)) {
      this.moveToPreviousChunk();
    } else {
      this.fixSide();
    }
  }

  /**
   * Move the cursor either to initialLineNumber or the first chunk and
   * reset scroll behavior.
   *
   * This may grab the focus from the app.
   *
   * If you do not want to move the cursor or grab focus, and just want to
   * reset the scroll behavior, use reInitAndUpdateStops() instead.
   */
  reInitCursor() {
    this.updateStops();
    if (!this.diffRowTR) {
      // does not scroll during init unless requested
      this.cursorManager.scrollMode = this.initialLineNumber
        ? ScrollMode.KEEP_VISIBLE
        : ScrollMode.NEVER;
      if (this.initialLineNumber) {
        this.moveToLineNumber(this.initialLineNumber, this.side);
        this.initialLineNumber = null;
      } else {
        this.moveToFirstChunk();
      }
    }
    this.resetScrollMode();
  }

  resetScrollMode() {
    this.cursorManager.scrollMode = ScrollMode.KEEP_VISIBLE;
  }

  private boundHandleWindowScroll = () => {
    if (this.preventAutoScrollOnManualScroll) {
      this.cursorManager.scrollMode = ScrollMode.NEVER;
      this.cursorManager.focusOnMove = false;
      this.preventAutoScrollOnManualScroll = false;
    }
  };

  reInitAndUpdateStops() {
    this.resetScrollMode();
    this.updateStops();
  }

  private boundHandleDiffLoadingChanged = () => {
    this.updateStops();
  };

  private boundHandleDiffRenderStart = () => {
    this.preventAutoScrollOnManualScroll = true;
  };

  private boundHandleDiffRenderContent = () => {
    this.updateStops();
    // When done rendering, turn focus on move and automatic scrolling back on
    this.cursorManager.focusOnMove = true;
    this.preventAutoScrollOnManualScroll = false;
  };

  private boundHandleDiffLineSelected = (
    e: CustomEvent<LineSelectedEventDetail>
  ) => {
    this.moveToLineNumber(e.detail.number, e.detail.side, e.detail.path);
  };

  createCommentInPlace() {
    const diffWithRangeSelected = this.getSelectedDiff();
    if (diffWithRangeSelected) {
      diffWithRangeSelected.createRangeComment();
    } else {
      const diffRow = this.getTargetDiffRow();
      const lineNumber = diffRow?.lineNumber(this.side);
      const diff = this.getTargetDiffElement();
      if (diff && lineNumber) {
        diff.addDraftAtLine(lineNumber, this.side);
      }
    }
  }

  getSelectedDiff() {
    return this.diffs.find(diff => diff.isRangeSelected());
  }

  getSelectedRange() {
    const diffWithRangeSelected = this.getSelectedDiff();
    if (diffWithRangeSelected) {
      return diffWithRangeSelected.getSelectedRange();
    }
    return undefined;
  }

  private getViewMode() {
    if (!this.diffRowTR) {
      return null;
    }

    if (this.diffRowTR.classList.contains('side-by-side')) {
      return DiffViewMode.SIDE_BY_SIDE;
    } else {
      return DiffViewMode.UNIFIED;
    }
  }

  private rowHasSide(row: Element) {
    const selector =
      (this.side === Side.LEFT ? '.left' : '.right') + ' + .content';
    return !!row.querySelector(selector);
  }

  private isFirstRowOfChunk(row: HTMLElement) {
    const chunk = fromRowToChunk(row);
    if (!chunk) return false;

    const isInDeltaChunk = chunk.classList.contains('delta');
    if (!isInDeltaChunk) return false;

    const firstRow = chunk.querySelector('tr:not(.moveControls)');
    return firstRow === row;
  }

  private rowHasThread(row: HTMLElement): boolean {
    const slots = [
      ...row.querySelectorAll<HTMLSlotElement>('.thread-group > slot'),
    ];
    return slots.some(slot => slot.assignedElements().length > 0);
  }

  /**
   * If we jumped to a row where there is no content on the current side then
   * switch to the alternate side.
   */
  private fixSide() {
    if (
      this.getViewMode() === DiffViewMode.SIDE_BY_SIDE &&
      this.isTargetBlank()
    ) {
      this.side = this.side === Side.LEFT ? Side.RIGHT : Side.LEFT;
    }
  }

  private isTargetBlank() {
    const line = this.getTargetDiffRow()?.line(this.side);
    return line?.type === GrDiffLineType.BLANK;
  }

  private fireCursorMoved(
    event: 'line-cursor-moved-out' | 'line-cursor-moved-in'
  ) {
    const lineNum = this.getTargetLineNumber();
    if (!lineNum) return;
    fire(this.diffRowTR, event, {lineNum, side: this.side});
  }

  private updateSideClass() {
    if (!this.diffRowTR) {
      return;
    }
    this.diffRowTR.classList.toggle(LEFT_SIDE_CLASS, this.side === Side.LEFT);
    this.diffRowTR.classList.toggle(RIGHT_SIDE_CLASS, this.side === Side.RIGHT);
  }

  // visible for testing
  updateStops() {
    this.cursorManager.stops = this.diffs.reduce(
      (stops: Stop[], diff) => stops.concat(diff.getCursorStops()),
      []
    );
  }

  replaceDiffs(diffs: GrDiffCursorable[]) {
    for (const diff of this.diffs) {
      this.removeEventListeners(diff);
    }
    this.diffs = [];
    for (const diff of diffs) {
      this.addEventListeners(diff);
    }
    this.diffs.push(...diffs);
    this.updateStops();
  }

  unregisterDiff(diff: GrDiffCursorable) {
    // This can happen during destruction - just don't unregister then.
    if (!this.diffs) return;
    const i = this.diffs.indexOf(diff);
    if (i !== -1) {
      this.diffs.splice(i, 1);
    }
  }

  private removeEventListeners(diff: GrDiffCursorable) {
    diff.removeEventListener(
      'loading-changed',
      this.boundHandleDiffLoadingChanged
    );
    diff.removeEventListener('render-start', this.boundHandleDiffRenderStart);
    diff.removeEventListener(
      'render-content',
      this.boundHandleDiffRenderContent
    );
    diff.removeEventListener('line-selected', this.boundHandleDiffLineSelected);
  }

  private addEventListeners(diff: GrDiffCursorable) {
    diff.addEventListener(
      'loading-changed',
      this.boundHandleDiffLoadingChanged
    );
    diff.addEventListener('render-start', this.boundHandleDiffRenderStart);
    diff.addEventListener('render-content', this.boundHandleDiffRenderContent);
    diff.addEventListener('line-selected', this.boundHandleDiffLineSelected);
  }

  // visible for testing
  findRowByNumberAndFile(
    targetNumber: LineNumber,
    side: Side,
    path?: string
  ): HTMLElement | undefined {
    let stops: Array<HTMLElement | AbortStop>;
    if (path) {
      const diff = this.diffs.filter(diff => diff.path === path)[0];
      stops = diff.getCursorStops();
    } else {
      stops = this.cursorManager.stops;
    }
    // Sadly needed for type narrowing to understand that the result is always
    // targetable.
    const targetableStops: HTMLElement[] = stops.filter(isTargetable);
    const selector = `.lineNum.${side}[data-value="${targetNumber}"]`;
    return targetableStops.find(stop => stop.querySelector(selector));
  }
}
