/**
 * @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 {BLANK_LINE, GrDiffLine, GrDiffLineType} from './gr-diff-line';
import {LineRange, Side} from '../../../api/diff';
import {LineNumber} from './gr-diff-line';

export enum GrDiffGroupType {
  /** Unchanged context. */
  BOTH = 'both',

  /** A widget used to show more context. */
  CONTEXT_CONTROL = 'contextControl',

  /** Added, removed or modified chunk. */
  DELTA = 'delta',
}

export interface GrDiffLinePair {
  left: GrDiffLine;
  right: GrDiffLine;
}

/**
 * Hides lines in the given range behind a context control group.
 *
 * Groups that would be partially visible are split into their visible and
 * hidden parts, respectively.
 * The groups need to be "common groups", meaning they have to have either
 * originated from an `ab` chunk, or from an `a`+`b` chunk with
 * `common: true`.
 *
 * If the hidden range is 3 lines or less, nothing is hidden and no context
 * control group is created.
 *
 * @param groups Common groups, ordered by their line ranges.
 * @param hiddenStart The first element to be hidden, as a
 *     non-negative line number offset relative to the first group's start
 *     line, left and right respectively.
 * @param hiddenEnd The first visible element after the hidden range,
 *     as a non-negative line number offset relative to the first group's
 *     start line, left and right respectively.
 */
export function hideInContextControl(
  groups: readonly GrDiffGroup[],
  hiddenStart: number,
  hiddenEnd: number
): GrDiffGroup[] {
  if (groups.length === 0) return [];
  // Clamp hiddenStart and hiddenEnd - inspired by e.g. substring
  hiddenStart = Math.max(hiddenStart, 0);
  hiddenEnd = Math.max(hiddenEnd, hiddenStart);

  let before: GrDiffGroup[] = [];
  let hidden = groups;
  let after: readonly GrDiffGroup[] = [];

  const numHidden = hiddenEnd - hiddenStart;

  // Showing a context control row for less than 4 lines does not make much,
  // because then that row would consume as much space as the collapsed code.
  if (numHidden > 3) {
    if (hiddenStart) {
      [before, hidden] = _splitCommonGroups(hidden, hiddenStart);
    }
    if (hiddenEnd) {
      let beforeLength = 0;
      if (before.length > 0) {
        const beforeStart = before[0].lineRange.left.start_line;
        const beforeEnd = before[before.length - 1].lineRange.left.end_line;
        beforeLength = beforeEnd - beforeStart + 1;
      }
      [hidden, after] = _splitCommonGroups(hidden, hiddenEnd - beforeLength);
    }
  } else {
    [hidden, after] = [[], hidden];
  }

  const result = [...before];
  if (hidden.length) {
    result.push(
      new GrDiffGroup({
        type: GrDiffGroupType.CONTEXT_CONTROL,
        contextGroups: [...hidden],
      })
    );
  }
  result.push(...after);
  return result;
}

/**
 * Splits a group in two, defined by leftSplit and rightSplit. Primarily to be
 * used in function _splitCommonGroups
 * Groups with some lines before and some lines after the split will be split
 * into two groups, which will be put into the first and second list.
 *
 * @param group The group to be split in two
 * @param leftSplit The line number relative to the split on the left side
 * @param rightSplit The line number relative to the split on the right side
 * @return two new groups, one before the split and another after it
 */
function _splitGroupInTwo(
  group: GrDiffGroup,
  leftSplit: number,
  rightSplit: number
) {
  let beforeSplit: GrDiffGroup | undefined;
  let afterSplit: GrDiffGroup | undefined;
  // split line is in the middle of a group, we need to break the group
  // in lines before and after the split.
  if (group.skip) {
    // Currently we assume skip chunks "refuse" to be split. Expanding this
    // group will in the future mean load more data - and therefore we want to
    // fire an event when user wants to do it.
    const closerToStartThanEnd =
      leftSplit - group.lineRange.left.start_line <
      group.lineRange.right.end_line - leftSplit;
    if (closerToStartThanEnd) {
      afterSplit = group;
    } else {
      beforeSplit = group;
    }
  } else {
    const before = [];
    const after = [];
    for (const line of group.lines) {
      if (
        (line.beforeNumber && line.beforeNumber < leftSplit) ||
        (line.afterNumber && line.afterNumber < rightSplit)
      ) {
        before.push(line);
      } else {
        after.push(line);
      }
    }
    if (before.length) {
      beforeSplit =
        before.length === group.lines.length
          ? group
          : group.cloneWithLines(before);
    }
    if (after.length) {
      afterSplit =
        after.length === group.lines.length
          ? group
          : group.cloneWithLines(after);
    }
  }
  return {beforeSplit, afterSplit};
}

/**
 * Splits a list of common groups into two lists of groups.
 *
 * Groups where all lines are before or all lines are after the split will be
 * retained as is and put into the first or second list respectively. Groups
 * with some lines before and some lines after the split will be split into
 * two groups, which will be put into the first and second list.
 *
 * @param split A line number offset relative to the first group's
 *     start line at which the groups should be split.
 * @return The outer array has 2 elements, the
 *   list of groups before and the list of groups after the split.
 */
function _splitCommonGroups(
  groups: readonly GrDiffGroup[],
  split: number
): GrDiffGroup[][] {
  if (groups.length === 0) return [[], []];
  const leftSplit = groups[0].lineRange.left.start_line + split;
  const rightSplit = groups[0].lineRange.right.start_line + split;

  const beforeGroups = [];
  const afterGroups = [];
  for (const group of groups) {
    const isCompletelyBefore =
      group.lineRange.left.end_line < leftSplit ||
      group.lineRange.right.end_line < rightSplit;
    const isCompletelyAfter =
      leftSplit <= group.lineRange.left.start_line ||
      rightSplit <= group.lineRange.right.start_line;
    if (isCompletelyBefore) {
      beforeGroups.push(group);
    } else if (isCompletelyAfter) {
      afterGroups.push(group);
    } else {
      const {beforeSplit, afterSplit} = _splitGroupInTwo(
        group,
        leftSplit,
        rightSplit
      );
      if (beforeSplit) {
        beforeGroups.push(beforeSplit);
      }
      if (afterSplit) {
        afterGroups.push(afterSplit);
      }
    }
  }
  return [beforeGroups, afterGroups];
}

export interface GrMoveDetails {
  changed: boolean;
  range?: {
    start: number;
    end: number;
  };
}

/** A chunk of the diff that should be rendered together. */
export class GrDiffGroup {
  constructor(
    options:
      | {
          type: GrDiffGroupType.BOTH | GrDiffGroupType.DELTA;
          lines?: GrDiffLine[];
          skip?: undefined;
          moveDetails?: GrMoveDetails;
          dueToRebase?: boolean;
          ignoredWhitespaceOnly?: boolean;
          keyLocation?: boolean;
        }
      | {
          type: GrDiffGroupType.BOTH | GrDiffGroupType.DELTA;
          lines?: undefined;
          skip: number;
          offsetLeft: number;
          offsetRight: number;
          moveDetails?: GrMoveDetails;
          dueToRebase?: boolean;
          ignoredWhitespaceOnly?: boolean;
          keyLocation?: boolean;
        }
      | {
          type: GrDiffGroupType.CONTEXT_CONTROL;
          contextGroups: GrDiffGroup[];
        }
  ) {
    this.type = options.type;
    switch (options.type) {
      case GrDiffGroupType.BOTH:
      case GrDiffGroupType.DELTA: {
        this.moveDetails = options.moveDetails;
        this.dueToRebase = options.dueToRebase ?? false;
        this.ignoredWhitespaceOnly = options.ignoredWhitespaceOnly ?? false;
        this.keyLocation = options.keyLocation ?? false;
        if (options.skip && options.lines) {
          throw new Error('Cannot set skip and lines');
        }
        this.skip = options.skip;
        if (options.skip) {
          this.lineRange = {
            left: {
              start_line: options.offsetLeft,
              end_line: options.offsetLeft + options.skip - 1,
            },
            right: {
              start_line: options.offsetRight,
              end_line: options.offsetRight + options.skip - 1,
            },
          };
        } else {
          for (const line of options.lines ?? []) {
            this.addLine(line);
          }
        }
        break;
      }
      case GrDiffGroupType.CONTEXT_CONTROL: {
        this.contextGroups = options.contextGroups;
        if (this.contextGroups.length > 0) {
          const firstGroup = this.contextGroups[0];
          const lastGroup = this.contextGroups[this.contextGroups.length - 1];
          this.lineRange = {
            left: {
              start_line: firstGroup.lineRange.left.start_line,
              end_line: lastGroup.lineRange.left.end_line,
            },
            right: {
              start_line: firstGroup.lineRange.right.start_line,
              end_line: lastGroup.lineRange.right.end_line,
            },
          };
        }
        break;
      }
      default:
        throw new Error(`Unknown group type: ${this.type}`);
    }
  }

  readonly type: GrDiffGroupType;

  readonly dueToRebase: boolean = false;

  /**
   * True means all changes in this line are whitespace changes that should
   * not be highlighted as changed as per the user settings.
   */
  readonly ignoredWhitespaceOnly: boolean = false;

  /**
   * True means it should not be collapsed (because it was in the URL, or
   * there is a comment on that line)
   */
  readonly keyLocation: boolean = false;

  /**
   * Once rendered the diff builder sets this to the diff section element.
   */
  element?: HTMLElement;

  readonly lines: GrDiffLine[] = [];

  readonly adds: GrDiffLine[] = [];

  readonly removes: GrDiffLine[] = [];

  readonly contextGroups: GrDiffGroup[] = [];

  readonly skip?: number;

  /** Both start and end line are inclusive. */
  readonly lineRange: {[side in Side]: LineRange} = {
    [Side.LEFT]: {start_line: 0, end_line: 0},
    [Side.RIGHT]: {start_line: 0, end_line: 0},
  };

  readonly moveDetails?: GrMoveDetails;

  /**
   * Creates a new group with the same properties but different lines.
   *
   * The element property is not copied, because the original element is still a
   * rendering of the old lines, so that would not make sense.
   */
  cloneWithLines(lines: GrDiffLine[]): GrDiffGroup {
    if (
      this.type !== GrDiffGroupType.BOTH &&
      this.type !== GrDiffGroupType.DELTA
    ) {
      throw new Error('Cannot clone context group with lines');
    }
    const group = new GrDiffGroup({
      type: this.type,
      lines,
      dueToRebase: this.dueToRebase,
      ignoredWhitespaceOnly: this.ignoredWhitespaceOnly,
    });
    return group;
  }

  private addLine(line: GrDiffLine) {
    this.lines.push(line);

    const notDelta =
      this.type === GrDiffGroupType.BOTH ||
      this.type === GrDiffGroupType.CONTEXT_CONTROL;
    if (
      notDelta &&
      (line.type === GrDiffLineType.ADD || line.type === GrDiffLineType.REMOVE)
    ) {
      throw Error('Cannot add delta line to a non-delta group.');
    }

    if (line.type === GrDiffLineType.ADD) {
      this.adds.push(line);
    } else if (line.type === GrDiffLineType.REMOVE) {
      this.removes.push(line);
    }
    this._updateRangeWithNewLine(line);
  }

  getSideBySidePairs(): GrDiffLinePair[] {
    if (
      this.type === GrDiffGroupType.BOTH ||
      this.type === GrDiffGroupType.CONTEXT_CONTROL
    ) {
      return this.lines.map(line => {
        return {
          left: line,
          right: line,
        };
      });
    }

    const pairs: GrDiffLinePair[] = [];
    let i = 0;
    let j = 0;
    while (i < this.removes.length || j < this.adds.length) {
      pairs.push({
        left: this.removes[i] || BLANK_LINE,
        right: this.adds[j] || BLANK_LINE,
      });
      i++;
      j++;
    }
    return pairs;
  }

  /** Returns true if it is, or contains, a skip group. */
  hasSkipGroup() {
    return !!this.skip || this.contextGroups?.some(g => !!g.skip);
  }

  containsLine(side: Side, line: LineNumber) {
    if (line === 'FILE' || line === 'LOST') {
      // For FILE and LOST, beforeNumber and afterNumber are the same
      return this.lines[0]?.beforeNumber === line;
    }
    const lineRange = this.lineRange[side];
    return lineRange.start_line <= line && line <= lineRange.end_line;
  }

  private _updateRangeWithNewLine(line: GrDiffLine) {
    if (
      line.beforeNumber === 'FILE' ||
      line.afterNumber === 'FILE' ||
      line.beforeNumber === 'LOST' ||
      line.afterNumber === 'LOST'
    ) {
      return;
    }

    if (line.type === GrDiffLineType.ADD || line.type === GrDiffLineType.BOTH) {
      if (
        this.lineRange.right.start_line === 0 ||
        line.afterNumber < this.lineRange.right.start_line
      ) {
        this.lineRange.right.start_line = line.afterNumber;
      }
      if (line.afterNumber > this.lineRange.right.end_line) {
        this.lineRange.right.end_line = line.afterNumber;
      }
    }

    if (
      line.type === GrDiffLineType.REMOVE ||
      line.type === GrDiffLineType.BOTH
    ) {
      if (
        this.lineRange.left.start_line === 0 ||
        line.beforeNumber < this.lineRange.left.start_line
      ) {
        this.lineRange.left.start_line = line.beforeNumber;
      }
      if (line.beforeNumber > this.lineRange.left.end_line) {
        this.lineRange.left.end_line = line.beforeNumber;
      }
    }
  }

  /**
   * Determines whether the group is either totally an addition or totally
   * a removal.
   */
  isTotal(): boolean {
    return (
      this.type === GrDiffGroupType.DELTA &&
      (!this.adds.length || !this.removes.length) &&
      !(!this.adds.length && !this.removes.length)
    );
  }
}
