/**
 * @license
 * Copyright (C) 2016 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 {
  MovedLinkClickedEventDetail,
  RenderPreferences,
} from '../../../api/diff';
import {fire} from '../../../utils/event-util';
import {GrDiffLine, GrDiffLineType, LineNumber} from '../gr-diff/gr-diff-line';
import {GrDiffGroup, GrDiffGroupType} from '../gr-diff/gr-diff-group';
import '../gr-context-controls/gr-context-controls';
import {
  GrContextControls,
  GrContextControlsShowConfig,
} from '../gr-context-controls/gr-context-controls';
import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
import {DiffViewMode, Side} from '../../../constants/constants';
import {DiffLayer} from '../../../types/types';
import {
  createBlameElement,
  createElementDiff,
  createElementDiffWithText,
  formatText,
  getResponsiveMode,
} from '../gr-diff/gr-diff-utils';
import {GrDiffBuilder} from './gr-diff-builder';
import {BlameInfo} from '../../../types/common';

function lineTdSelector(lineNumber: LineNumber, side?: Side): string {
  const sideSelector = side ? `.${side}` : '';
  return `td.lineNum[data-value="${lineNumber}"]${sideSelector}`;
}
/**
 * Base class for builders that are creating the DOM elements programmatically
 * by calling `document.createElement()` and such. We are calling such builders
 * "legacy", because we want to create (Lit) component based diff elements.
 *
 * TODO: Do not subclass `GrDiffBuilder`. Use composition and interfaces.
 */
export abstract class GrDiffBuilderLegacy extends GrDiffBuilder {
  constructor(
    diff: DiffInfo,
    prefs: DiffPreferencesInfo,
    outputEl: HTMLElement,
    layers: DiffLayer[] = [],
    renderPrefs?: RenderPreferences
  ) {
    super(diff, prefs, outputEl, layers, renderPrefs);
  }

  override getContentTdByLine(
    lineNumber: LineNumber,
    side?: Side,
    root: Element = this.outputEl
  ): HTMLTableCellElement | null {
    return root.querySelector<HTMLTableCellElement>(
      `${lineTdSelector(lineNumber, side)} ~ td.content`
    );
  }

  override getLineElByNumber(
    lineNumber: LineNumber,
    side?: Side
  ): HTMLTableCellElement | null {
    return this.outputEl.querySelector<HTMLTableCellElement>(
      lineTdSelector(lineNumber, side)
    );
  }

  override getLineNumberRows() {
    return Array.from(
      this.outputEl.querySelectorAll<HTMLTableRowElement>(
        ':not(.contextControl) > .diff-row'
      ) ?? []
    ).filter(tr => tr.querySelector('button'));
  }

  override getLineNumEls(side: Side): HTMLTableCellElement[] {
    return Array.from(
      this.outputEl.querySelectorAll<HTMLTableCellElement>(
        `td.lineNum.${side}`
      ) ?? []
    );
  }

  override getBlameTdByLine(lineNum: number): Element | undefined {
    return (
      this.outputEl.querySelector(`td.blame[data-line-number="${lineNum}"]`) ??
      undefined
    );
  }

  override getContentByLine(
    lineNumber: LineNumber,
    side?: Side,
    root?: HTMLElement
  ): HTMLElement | null {
    const td = this.getContentTdByLine(lineNumber, side, root);
    return td ? td.querySelector('.contentText') : null;
  }

  override renderContentByRange(
    start: LineNumber,
    end: LineNumber,
    side: Side
  ) {
    const lines: GrDiffLine[] = [];
    const elements: HTMLElement[] = [];
    let line;
    let el;
    this.findLinesByRange(start, end, side, lines, elements);
    for (let i = 0; i < lines.length; i++) {
      line = lines[i];
      el = elements[i];
      if (!el || !el.parentElement) {
        // Cannot re-render an element if it does not exist. This can happen
        // if lines are collapsed and not visible on the page yet.
        continue;
      }
      const lineNumberEl = this.getLineNumberEl(el, side);
      el.parentElement.replaceChild(
        this.createTextEl(lineNumberEl, line, side).firstChild!,
        el
      );
    }
  }

  override renderBlameByRange(blame: BlameInfo, start: number, end: number) {
    for (let i = start; i <= end; i++) {
      // TODO(wyatta): this query is expensive, but, when traversing a
      // range, the lines are consecutive, and given the previous blame
      // cell, the next one can be reached cheaply.
      const blameCell = this.getBlameTdByLine(i);
      if (!blameCell) continue;

      // Remove the element's children (if any).
      while (blameCell.hasChildNodes()) {
        blameCell.removeChild(blameCell.lastChild!);
      }
      const blameEl = createBlameElement(i, blame);
      if (blameEl) blameCell.appendChild(blameEl);
    }
  }

  /**
   * Finds the line number element given the content element by walking up the
   * DOM tree to the diff row and then querying for a .lineNum element on the
   * requested side.
   *
   * TODO(brohlfs): Consolidate this with getLineEl... methods in html file.
   */
  private getLineNumberEl(
    content: HTMLElement,
    side: Side
  ): HTMLElement | null {
    let row: HTMLElement | null = content;
    while (row && !row.classList.contains('diff-row')) row = row.parentElement;
    return row ? (row.querySelector('.lineNum.' + side) as HTMLElement) : null;
  }

  /**
   * Adds <tr> table rows to a <tbody> section for allowing the user to expand
   * collapsed of lines. Called by subclasses.
   */
  protected createContextControls(
    section: HTMLElement,
    group: GrDiffGroup,
    viewMode: DiffViewMode
  ) {
    const leftStart = group.lineRange.left.start_line;
    const leftEnd = group.lineRange.left.end_line;
    const firstGroupIsSkipped = !!group.contextGroups[0].skip;
    const lastGroupIsSkipped =
      !!group.contextGroups[group.contextGroups.length - 1].skip;

    const containsWholeFile = this.numLinesLeft === leftEnd - leftStart + 1;
    const showAbove =
      (leftStart > 1 && !firstGroupIsSkipped) || containsWholeFile;
    const showBelow = leftEnd < this.numLinesLeft && !lastGroupIsSkipped;

    if (showAbove) {
      const paddingRow = this.createContextControlPaddingRow(viewMode);
      paddingRow.classList.add('above');
      section.appendChild(paddingRow);
    }
    section.appendChild(
      this.createContextControlRow(group, showAbove, showBelow, viewMode)
    );
    if (showBelow) {
      const paddingRow = this.createContextControlPaddingRow(viewMode);
      paddingRow.classList.add('below');
      section.appendChild(paddingRow);
    }
  }

  /**
   * Creates a context control <tr> table row for with buttons the allow the
   * user to expand collapsed lines. Buttons extend from the gap created by this
   * method up or down into the area of code that they affect.
   */
  private createContextControlRow(
    group: GrDiffGroup,
    showAbove: boolean,
    showBelow: boolean,
    viewMode: DiffViewMode
  ): HTMLElement {
    const row = createElementDiff('tr', 'dividerRow');
    let showConfig: GrContextControlsShowConfig;
    if (showAbove && !showBelow) {
      showConfig = 'above';
    } else if (!showAbove && showBelow) {
      showConfig = 'below';
    } else {
      // Note that !showAbove && !showBelow also intentionally creates
      // "show-both". This means the file is completely collapsed, which is
      // unusual, but at least happens in one test.
      showConfig = 'both';
    }
    row.classList.add(`show-${showConfig}`);

    row.appendChild(this.createBlameCell(0));
    if (viewMode === DiffViewMode.SIDE_BY_SIDE) {
      row.appendChild(createElementDiff('td'));
    }

    const cell = createElementDiff('td', 'dividerCell');
    cell.setAttribute('colspan', '3');
    row.appendChild(cell);

    const contextControls = createElementDiff(
      'gr-context-controls'
    ) as GrContextControls;
    contextControls.diff = this._diff;
    contextControls.renderPreferences = this.renderPrefs;
    contextControls.group = group;
    contextControls.showConfig = showConfig;
    cell.appendChild(contextControls);
    return row;
  }

  /**
   * Creates a table row to serve as padding between code and context controls.
   * Blame column, line gutters, and content area will continue visually, but
   * context controls can render over this background to map more clearly to
   * the area of code they expand.
   */
  private createContextControlPaddingRow(viewMode: DiffViewMode) {
    const row = createElementDiff('tr', 'contextBackground');

    if (viewMode === DiffViewMode.SIDE_BY_SIDE) {
      row.classList.add('side-by-side');
      row.setAttribute('left-type', GrDiffGroupType.CONTEXT_CONTROL);
      row.setAttribute('right-type', GrDiffGroupType.CONTEXT_CONTROL);
    } else {
      row.classList.add('unified');
    }

    row.appendChild(this.createBlameCell(0));
    row.appendChild(createElementDiff('td', 'contextLineNum'));
    if (viewMode === DiffViewMode.SIDE_BY_SIDE) {
      row.appendChild(createElementDiff('td'));
    }
    row.appendChild(createElementDiff('td', 'contextLineNum'));
    row.appendChild(createElementDiff('td'));

    return row;
  }

  protected createLineEl(
    line: GrDiffLine,
    number: LineNumber,
    type: GrDiffLineType,
    side: Side
  ) {
    const td = createElementDiff('td');
    td.classList.add(side);
    if (line.type === GrDiffLineType.BLANK) {
      return td;
    }
    if (line.type === GrDiffLineType.BOTH || line.type === type) {
      td.classList.add('lineNum');
      td.dataset['value'] = number.toString();

      if (
        ((this._prefs.show_file_comment_button === false ||
          this.renderPrefs?.show_file_comment_button === false) &&
          number === 'FILE') ||
        number === 'LOST'
      ) {
        return td;
      }

      const button = createElementDiff('button');
      td.appendChild(button);
      button.tabIndex = -1;
      button.classList.add('lineNumButton');
      button.classList.add(side);
      button.dataset['value'] = number.toString();
      button.textContent = number === 'FILE' ? 'File' : number.toString();
      if (number === 'FILE') {
        button.setAttribute('aria-label', 'Add file comment');
      }

      // Add aria-labels for valid line numbers.
      // For unified diff, this method will be called with number set to 0 for
      // the empty line number column for added/removed lines. This should not
      // be announced to the screenreader.
      if (number > 0) {
        if (line.type === GrDiffLineType.REMOVE) {
          button.setAttribute('aria-label', `${number} removed`);
        } else if (line.type === GrDiffLineType.ADD) {
          button.setAttribute('aria-label', `${number} added`);
        }
      }
      this.addLineNumberMouseEvents(td, number, side);
    }
    return td;
  }

  private addLineNumberMouseEvents(
    el: HTMLElement,
    number: LineNumber,
    side: Side
  ) {
    el.addEventListener('mouseenter', () => {
      fire(el, 'line-mouse-enter', {lineNum: number, side});
    });
    el.addEventListener('mouseleave', () => {
      fire(el, 'line-mouse-leave', {lineNum: number, side});
    });
  }

  protected createTextEl(
    lineNumberEl: HTMLElement | null,
    line: GrDiffLine,
    side?: Side
  ) {
    const td = createElementDiff('td');
    if (line.type !== GrDiffLineType.BLANK) {
      td.classList.add('content');
    }
    if (side) {
      td.classList.add(side);
    }

    // If intraline info is not available, the entire line will be
    // considered as changed and marked as dark red / green color
    if (!line.hasIntralineInfo) {
      td.classList.add('no-intraline-info');
    }
    td.classList.add(line.type);

    const {beforeNumber, afterNumber} = line;
    if (beforeNumber !== 'FILE' && beforeNumber !== 'LOST') {
      const responsiveMode = getResponsiveMode(this._prefs, this.renderPrefs);
      const contentText = formatText(
        line.text,
        responsiveMode,
        this._prefs.tab_size,
        this._prefs.line_length
      );

      if (side) {
        contentText.setAttribute('data-side', side);
        const number = side === Side.LEFT ? beforeNumber : afterNumber;
        this.addLineNumberMouseEvents(td, number, side);
      }

      if (lineNumberEl && side) {
        for (const layer of this.layers) {
          if (typeof layer.annotate === 'function') {
            layer.annotate(contentText, lineNumberEl, line, side);
          }
        }
      } else {
        console.error('lineNumberEl or side not set, skipping layer.annotate');
      }

      td.appendChild(contentText);
    } else if (line.beforeNumber === 'FILE') td.classList.add('file');
    else if (line.beforeNumber === 'LOST') td.classList.add('lost');

    return td;
  }

  private createMovedLineAnchor(line: number, side: Side) {
    const anchor = createElementDiffWithText('a', `${line}`);

    // href is not actually used but important for Screen Readers
    anchor.setAttribute('href', `#${line}`);
    anchor.addEventListener('click', e => {
      e.preventDefault();
      anchor.dispatchEvent(
        new CustomEvent<MovedLinkClickedEventDetail>('moved-link-clicked', {
          detail: {
            lineNum: line,
            side,
          },
          composed: true,
          bubbles: true,
        })
      );
    });
    return anchor;
  }

  private createMoveDescriptionDiv(movedIn: boolean, group: GrDiffGroup) {
    const div = createElementDiff('div');
    if (group.moveDetails?.range) {
      const {changed, range} = group.moveDetails;
      const otherSide = movedIn ? Side.LEFT : Side.RIGHT;
      const andChangedLabel = changed ? 'and changed ' : '';
      const direction = movedIn ? 'from' : 'to';
      const textLabel = `Moved ${andChangedLabel}${direction} lines `;
      div.appendChild(createElementDiffWithText('span', textLabel));
      div.appendChild(this.createMovedLineAnchor(range.start, otherSide));
      div.appendChild(createElementDiffWithText('span', ' - '));
      div.appendChild(this.createMovedLineAnchor(range.end, otherSide));
    } else {
      div.appendChild(
        createElementDiffWithText('span', movedIn ? 'Moved in' : 'Moved out')
      );
    }
    return div;
  }

  protected buildMoveControls(group: GrDiffGroup) {
    const movedIn = group.adds.length > 0;
    const {numberOfCells, movedOutIndex, movedInIndex, lineNumberCols} =
      this.getMoveControlsConfig();

    let controlsClass;
    let descriptionIndex;
    const descriptionTextDiv = this.createMoveDescriptionDiv(movedIn, group);
    if (movedIn) {
      controlsClass = 'movedIn';
      descriptionIndex = movedInIndex;
    } else {
      controlsClass = 'movedOut';
      descriptionIndex = movedOutIndex;
    }

    const controls = createElementDiff('tr', `moveControls ${controlsClass}`);
    const cells = [...Array(numberOfCells).keys()].map(() =>
      createElementDiff('td')
    );
    lineNumberCols.forEach(index => {
      cells[index].classList.add('moveControlsLineNumCol');
    });

    const moveRangeHeader = createElementDiff('gr-range-header');
    moveRangeHeader.setAttribute('icon', 'gr-icons:move-item');
    moveRangeHeader.appendChild(descriptionTextDiv);
    cells[descriptionIndex].classList.add('moveHeader');
    cells[descriptionIndex].appendChild(moveRangeHeader);
    cells.forEach(c => {
      controls.appendChild(c);
    });
    return controls;
  }

  /**
   * Create a blame cell for the given base line. Blame information will be
   * included in the cell if available.
   */
  protected createBlameCell(lineNumber: LineNumber): HTMLTableCellElement {
    const blameTd = createElementDiff('td', 'blame') as HTMLTableCellElement;
    blameTd.setAttribute('data-line-number', lineNumber.toString());
    if (!lineNumber) return blameTd;

    const blameInfo = this.getBlameCommitForBaseLine(lineNumber);
    if (!blameInfo) return blameTd;

    blameTd.appendChild(createBlameElement(lineNumber, blameInfo));
    return blameTd;
  }
}
