/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import './gr-diff-section';
import '../gr-context-controls/gr-context-controls';
import {
  ContentLoadNeededEventDetail,
  DiffContextExpandedExternalDetail,
  DiffViewMode,
  LineNumber,
  RenderPreferences,
} from '../../../api/diff';
import {GrDiffGroup} from '../gr-diff/gr-diff-group';
import {BlameInfo} from '../../../types/common';
import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
import {Side} from '../../../constants/constants';
import {DiffLayer, isDefined} from '../../../types/types';
import {GrDiffRow} from './gr-diff-row';
import {GrDiffSection} from './gr-diff-section';
import {html, render} from 'lit';
import {diffClasses} from '../../diff/gr-diff/gr-diff-utils';
import {when} from 'lit/directives/when.js';
import {GrDiffBuilderImage} from './gr-diff-builder-image';
import {GrDiffBuilderBinary} from './gr-diff-builder-binary';

export interface DiffContextExpandedEventDetail
  extends DiffContextExpandedExternalDetail {
  /** The context control group that should be replaced by `groups`. */
  contextGroup: GrDiffGroup;
  groups: GrDiffGroup[];
}

declare global {
  interface HTMLElementEventMap {
    'diff-context-expanded-internal-new': CustomEvent<DiffContextExpandedEventDetail>;
    'diff-context-expanded': CustomEvent<DiffContextExpandedExternalDetail>;
    'content-load-needed': CustomEvent<ContentLoadNeededEventDetail>;
  }
}

export function isImageDiffBuilder<T extends GrDiffBuilder>(
  x: T | GrDiffBuilderImage | undefined
): x is GrDiffBuilderImage {
  return !!x && !!(x as GrDiffBuilderImage).renderImageDiff;
}

export function isBinaryDiffBuilder<T extends GrDiffBuilder>(
  x: T | GrDiffBuilderBinary | undefined
): x is GrDiffBuilderBinary {
  return !!x && !!(x as GrDiffBuilderBinary).renderBinaryDiff;
}

/**
 * The builder takes GrDiffGroups, and builds the corresponding DOM elements,
 * called sections. Only the builder should add or remove sections from the
 * DOM. Callers can use the ...group() methods to modify groups and thus cause
 * rendering changes.
 */
export class GrDiffBuilder {
  private readonly diff: DiffInfo;

  readonly prefs: DiffPreferencesInfo;

  renderPrefs?: RenderPreferences;

  readonly outputEl: HTMLElement;

  private groups: GrDiffGroup[];

  private readonly layerUpdateListener: (
    start: LineNumber,
    end: LineNumber,
    side: Side
  ) => void;

  constructor(
    diff: DiffInfo,
    prefs: DiffPreferencesInfo,
    outputEl: HTMLElement,
    readonly layers: DiffLayer[] = [],
    renderPrefs?: RenderPreferences
  ) {
    this.diff = diff;
    this.prefs = prefs;
    this.renderPrefs = renderPrefs;
    this.outputEl = outputEl;
    this.groups = [];

    if (isNaN(prefs.tab_size) || prefs.tab_size <= 0) {
      throw Error('Invalid tab size from preferences.');
    }

    if (isNaN(prefs.line_length) || prefs.line_length <= 0) {
      throw Error('Invalid line length from preferences.');
    }

    this.layerUpdateListener = (
      start: LineNumber,
      end: LineNumber,
      side: Side
    ) => this.renderContentByRange(start, end, side);
    this.init();
  }

  getContentTdByLine(
    lineNumber: LineNumber,
    side?: Side
  ): HTMLTableCellElement | undefined {
    if (!side) return undefined;
    const row = this.findRow(lineNumber, side);
    return row?.getContentCell(side);
  }

  getLineElByNumber(
    lineNumber: LineNumber,
    side?: Side
  ): HTMLTableCellElement | undefined {
    if (!side) return undefined;
    const row = this.findRow(lineNumber, side);
    return row?.getLineNumberCell(side);
  }

  private findRow(lineNumber?: LineNumber, side?: Side): GrDiffRow | undefined {
    if (!side || !lineNumber) return undefined;
    const group = this.findGroup(side, lineNumber);
    if (!group) return undefined;
    const section = this.findSection(group);
    if (!section) return undefined;
    return section.findRow(side, lineNumber);
  }

  private getDiffRows() {
    const sections = [
      ...this.outputEl.querySelectorAll<GrDiffSection>('gr-diff-section'),
    ];
    return sections.map(s => s.getDiffRows()).flat();
  }

  getLineNumberRows(): HTMLTableRowElement[] {
    const rows = this.getDiffRows();
    return rows.map(r => r.getTableRow()).filter(isDefined);
  }

  getLineNumEls(side: Side): HTMLTableCellElement[] {
    const rows = this.getDiffRows();
    return rows.map(r => r.getLineNumberCell(side)).filter(isDefined);
  }

  /** This is used when layers initiate an update. */
  renderContentByRange(start: LineNumber, end: LineNumber, side: Side) {
    const groups = this.getGroupsByLineRange(start, end, side);
    for (const group of groups) {
      const section = this.findSection(group);
      for (const row of section?.getDiffRows() ?? []) {
        row.requestUpdate();
      }
    }
  }

  private findSection(group: GrDiffGroup): GrDiffSection | undefined {
    const leftClass = `left-${group.startLine(Side.LEFT)}`;
    const rightClass = `right-${group.startLine(Side.RIGHT)}`;
    return (
      this.outputEl.querySelector<GrDiffSection>(
        `gr-diff-section.${leftClass}.${rightClass}`
      ) ?? undefined
    );
  }

  buildSectionElement(group: GrDiffGroup): HTMLElement {
    const leftCl = `left-${group.startLine(Side.LEFT)}`;
    const rightCl = `right-${group.startLine(Side.RIGHT)}`;
    const section = html`
      <gr-diff-section
        class="${leftCl} ${rightCl}"
        .group=${group}
        .diff=${this.diff}
        .layers=${this.layers}
        .diffPrefs=${this.prefs}
        .renderPrefs=${this.renderPrefs}
      ></gr-diff-section>
    `;
    // When using Lit's `render()` method it wants to be in full control of the
    // element that it renders into, so we let it render into a temp element.
    // Rendering into the diff table directly would interfere with
    // `clearDiffContent()`for example.
    // TODO: Convert <gr-diff> to be fully lit controlled and incorporate this
    // method into Lit's `render()` cycle.
    const tempEl = document.createElement('div');
    render(section, tempEl);
    const sectionEl = tempEl.firstElementChild as GrDiffSection;
    return sectionEl;
  }

  addColumns(outputEl: HTMLElement, lineNumberWidth: number): void {
    const colgroup = html`
      <colgroup>
        <col class=${diffClasses('blame')}></col>
        ${when(
          this.renderPrefs?.view_mode === DiffViewMode.UNIFIED,
          () => html` ${this.renderUnifiedColumns(lineNumberWidth)} `,
          () => html`
            ${this.renderSideBySideColumns(Side.LEFT, lineNumberWidth)}
            ${this.renderSideBySideColumns(Side.RIGHT, lineNumberWidth)}
          `
        )}
      </colgroup>
    `;
    // When using Lit's `render()` method it wants to be in full control of the
    // element that it renders into, so we let it render into a temp element.
    // Rendering into the diff table directly would interfere with
    // `clearDiffContent()`for example.
    // TODO: Convert <gr-diff> to be fully lit controlled and incorporate this
    // method into Lit's `render()` cycle.
    const tempEl = document.createElement('div');
    render(colgroup, tempEl);
    const colgroupEl = tempEl.firstElementChild as HTMLElement;
    outputEl.appendChild(colgroupEl);
  }

  private renderUnifiedColumns(lineNumberWidth: number) {
    return html`
      <col class=${diffClasses()} width=${lineNumberWidth}></col>
      <col class=${diffClasses()} width=${lineNumberWidth}></col>
      <col class=${diffClasses()}></col>
    `;
  }

  private renderSideBySideColumns(side: Side, lineNumberWidth: number) {
    return html`
      <col class=${diffClasses(side)} width=${lineNumberWidth}></col>
      <col class=${diffClasses(side, 'sign')}></col>
      <col class=${diffClasses(side)}></col>
    `;
  }

  /**
   * This is meant to be called when the gr-diff component re-connects, or when
   * the diff is (re-)rendered.
   *
   * Make sure that this method is symmetric with cleanup(), which is called
   * when gr-diff disconnects.
   */
  init() {
    this.cleanup();
    for (const layer of this.layers) {
      if (layer.addListener) {
        layer.addListener(this.layerUpdateListener);
      }
    }
  }

  /**
   * This is meant to be called when the gr-diff component disconnects, or when
   * the diff is (re-)rendered.
   *
   * Make sure that this method is symmetric with init(), which is called when
   * gr-diff re-connects.
   */
  cleanup() {
    for (const layer of this.layers) {
      if (layer.removeListener) {
        layer.removeListener(this.layerUpdateListener);
      }
    }
  }

  addGroups(groups: readonly GrDiffGroup[]) {
    for (const group of groups) {
      this.groups.push(group);
      this.emitGroup(group);
    }
  }

  clearGroups() {
    for (const deletedGroup of this.groups) {
      deletedGroup.element?.remove();
    }
    this.groups = [];
  }

  replaceGroup(contextControl: GrDiffGroup, groups: readonly GrDiffGroup[]) {
    const i = this.groups.indexOf(contextControl);
    if (i === -1) throw new Error('cannot find context control group');

    const contextControlSection = this.groups[i].element;
    if (!contextControlSection) throw new Error('diff group element not set');

    this.groups.splice(i, 1, ...groups);
    for (const group of groups) {
      this.emitGroup(group, contextControlSection);
    }
    if (contextControlSection) contextControlSection.remove();
  }

  findGroup(side: Side, line: LineNumber) {
    return this.groups.find(group => group.containsLine(side, line));
  }

  private emitGroup(group: GrDiffGroup, beforeSection?: HTMLElement) {
    const element = this.buildSectionElement(group);
    this.outputEl.insertBefore(element, beforeSection ?? null);
    group.element = element;
  }

  // visible for testing
  getGroupsByLineRange(
    startLine: LineNumber,
    endLine: LineNumber,
    side: Side
  ): GrDiffGroup[] {
    const startIndex = this.groups.findIndex(group =>
      group.containsLine(side, startLine)
    );
    if (startIndex === -1) return [];
    let endIndex = this.groups.findIndex(group =>
      group.containsLine(side, endLine)
    );
    // Not all groups may have been processed yet (i.e. this.groups is still
    // incomplete). In that case let's just return *all* groups until the end
    // of the array.
    if (endIndex === -1) endIndex = this.groups.length - 1;
    // The filter preserves the legacy behavior to only return non-context
    // groups
    return this.groups
      .slice(startIndex, endIndex + 1)
      .filter(group => group.lines.length > 0);
  }

  /**
   * Set the blame information for the diff. For any already-rendered line,
   * re-render its blame cell content.
   */
  setBlame(blame: BlameInfo[]) {
    for (const blameInfo of blame) {
      for (const range of blameInfo.ranges) {
        for (let line = range.start; line <= range.end; line++) {
          const row = this.findRow(line, Side.LEFT);
          if (row) row.blameInfo = blameInfo;
        }
      }
    }
  }

  /**
   * Only special builders need to implement this. The default is to
   * just ignore it.
   */
  updateRenderPrefs(_: RenderPreferences) {}
}
