/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {BlameInfo, CommentRange} from '../../../types/common';
import {Side, SpecialFilePath} from '../../../constants/constants';
import {
  DiffContextExpandedExternalDetail,
  DiffPreferencesInfo,
  DiffResponsiveMode,
  DisplayLine,
  FILE,
  LOST,
  LineNumber,
  RenderPreferences,
} from '../../../api/diff';
import {GrDiffGroup} from './gr-diff-group';

/**
 * In JS, unicode code points above 0xFFFF occupy two elements of a string.
 * For example '𐀏'.length is 2. An occurrence of such a code point is called a
 * surrogate pair.
 *
 * This regex segments a string along tabs ('\t') and surrogate pairs, since
 * these are two cases where '1 char' does not automatically imply '1 column'.
 *
 * TODO: For human languages whose orthographies use combining marks, this
 * approach won't correctly identify the grapheme boundaries. In those cases,
 * a grapheme consists of multiple code points that should count as only one
 * character against the column limit. Getting that correct (if it's desired)
 * is probably beyond the limits of a regex, but there are nonstandard APIs to
 * do this, and proposed (but, as of Nov 2017, unimplemented) standard APIs.
 *
 * Further reading:
 *   On Unicode in JS: https://mathiasbynens.be/notes/javascript-unicode
 *   Graphemes: http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
 *   A proposed JS API: https://github.com/tc39/proposal-intl-segmenter
 */
export const REGEX_TAB_OR_SURROGATE_PAIR = /\t|[\uD800-\uDBFF][\uDC00-\uDFFF]/;

export function getResponsiveMode(
  prefs?: DiffPreferencesInfo,
  renderPrefs?: RenderPreferences
): DiffResponsiveMode {
  if (renderPrefs?.responsive_mode) {
    return renderPrefs.responsive_mode;
  }
  // Backwards compatibility to the line_wrapping param.
  if (prefs?.line_wrapping) {
    return 'FULL_RESPONSIVE';
  }
  return 'NONE';
}

export function isResponsive(responsiveMode?: DiffResponsiveMode) {
  return (
    responsiveMode === 'FULL_RESPONSIVE' || responsiveMode === 'SHRINK_ONLY'
  );
}

/**
 * Compare two ranges. Either argument may be falsy, but will only return
 * true if both are falsy or if neither are falsy and have the same position
 * values.
 */
export function rangesEqual(a?: CommentRange, b?: CommentRange): boolean {
  if (!a && !b) {
    return true;
  }
  if (!a || !b) {
    return false;
  }
  return (
    a.start_line === b.start_line &&
    a.start_character === b.start_character &&
    a.end_line === b.end_line &&
    a.end_character === b.end_character
  );
}

export function isLongCommentRange(range: CommentRange): boolean {
  return range.end_line - range.start_line > 10;
}

export function getLineNumberByChild(node?: Node) {
  return getLineNumber(getLineElByChild(node));
}

export function lineNumberToNumber(lineNumber?: LineNumber | null): number {
  if (typeof lineNumber !== 'number') return 0;
  return lineNumber;
}

export function getLineElByChild(node?: Node): HTMLElement | null {
  while (node) {
    if (node instanceof Element) {
      if (node.classList.contains('lineNum')) {
        return node as HTMLElement;
      }
      if (node.classList.contains('section')) {
        return null;
      }
    }
    node =
      (node as Element).assignedSlot ??
      (node as ShadowRoot).host ??
      node.previousSibling ??
      node.parentNode ??
      undefined;
  }
  return null;
}

export function getSideByLineEl(lineEl: Element) {
  return lineEl.classList.contains(Side.RIGHT) ? Side.RIGHT : Side.LEFT;
}

export function getLineNumber(lineEl?: Element | null): LineNumber | null {
  if (!lineEl) return null;
  const lineNumberStr = lineEl.getAttribute('data-value');
  if (!lineNumberStr) return null;
  if (lineNumberStr === FILE) return FILE;
  if (lineNumberStr === LOST) return LOST;
  const lineNumber = Number(lineNumberStr);
  return Number.isInteger(lineNumber) ? lineNumber : null;
}

export function getLine(threadEl: HTMLElement): LineNumber {
  const lineAtt = threadEl.getAttribute('line-num');
  if (lineAtt === LOST) return lineAtt;
  if (!lineAtt || lineAtt === FILE) return FILE;
  const line = Number(lineAtt);
  if (isNaN(line)) throw new Error(`cannot parse line number: ${lineAtt}`);
  if (line < 1) throw new Error(`line number smaller than 1: ${line}`);
  return line;
}

export function getSide(threadEl: HTMLElement): Side | undefined {
  const sideAtt = threadEl.getAttribute('diff-side');
  if (!sideAtt) {
    console.warn('comment thread without side');
    return undefined;
  }
  if (sideAtt !== Side.LEFT && sideAtt !== Side.RIGHT)
    throw Error(`unexpected value for side: ${sideAtt}`);
  return sideAtt as Side;
}

export function getRange(threadEl: HTMLElement): CommentRange | undefined {
  const rangeAtt = threadEl.getAttribute('range');
  if (!rangeAtt) return undefined;
  const range = JSON.parse(rangeAtt) as CommentRange;
  if (!range.start_line) return undefined;
  return range;
}

/**
 * This is all the data that gr-diff extracts from comment thread elements,
 * see `GrDiffThreadElement`. Otherwise gr-diff treats such elements as a black
 * box.
 */
export interface GrDiffCommentThread {
  side: Side;
  line: LineNumber;
  range?: CommentRange;
  rootId?: string;
}

/**
 * Retrieves all the data from a comment thread element that the gr-diff API
 * contract defines for such elements.
 */
export function getDataFromCommentThreadEl(
  threadEl?: EventTarget | null
): GrDiffCommentThread | undefined {
  if (!isThreadEl(threadEl)) return undefined;
  const side = getSide(threadEl);
  const line = getLine(threadEl);
  const range = getRange(threadEl);
  if (!side) return undefined;
  if (!line) return undefined;
  return {side, line, range, rootId: threadEl.rootId};
}

export interface KeyLocations {
  left: {[key: string]: boolean};
  right: {[key: string]: boolean};
}

/**
 * "Context" is the number of lines that we are showing around diff chunks and
 * commented lines. This typically comes from a user preference and is set to
 * something like 3 or 10.
 *
 * `FULL_CONTEXT` means that the user wants to see the entire file. We could
 * also call this "infinite context".
 */
export const FULL_CONTEXT = -1;

export enum FullContext {
  /** User has opted into showing the full context. */
  YES = 'YES',
  /** User has opted into showing only limited context. */
  NO = 'NO',
  /**
   * User has not decided yet. Will see a warning message with two options then,
   * if the file is too large.
   */
  UNDECIDED = 'UNDECIDED',
}

export function computeContext(
  prefsContext: number | undefined,
  showFullContext: FullContext,
  defaultContext: number
) {
  if (showFullContext === FullContext.YES) {
    return FULL_CONTEXT;
  }
  if (
    prefsContext !== undefined &&
    !(showFullContext === FullContext.NO && prefsContext === FULL_CONTEXT)
  ) {
    return prefsContext;
  }
  return defaultContext;
}

export function computeLineLength(
  prefs: DiffPreferencesInfo,
  path: string | undefined
): number {
  if (path === SpecialFilePath.COMMIT_MESSAGE) {
    return 72;
  }
  const lineLength = prefs.line_length;
  if (Number.isInteger(lineLength) && lineLength > 0) {
    return lineLength;
  }
  return 100;
}

export function computeKeyLocations(
  lineOfInterest: DisplayLine | undefined,
  comments: GrDiffCommentThread[]
) {
  const keyLocations: KeyLocations = {left: {}, right: {}};

  if (lineOfInterest) {
    keyLocations[lineOfInterest.side][lineOfInterest.lineNum] = true;
  }

  for (const comment of comments) {
    keyLocations[comment.side][comment.line] = true;
    if (comment.range?.start_line) {
      keyLocations[comment.side][comment.range.start_line] = true;
    }
  }

  return keyLocations;
}

export function compareComments(
  c1: GrDiffCommentThread,
  c2: GrDiffCommentThread
): number {
  if (c1.side !== c2.side) {
    return c1.side === Side.RIGHT ? 1 : -1;
  }

  if (c1.line !== c2.line) {
    if (c1.line === FILE && c2.line !== FILE) return -1;
    if (c1.line !== FILE && c2.line === FILE) return 1;
    if (c1.line === LOST && c2.line !== LOST) return -1;
    if (c1.line !== LOST && c2.line === LOST) return 1;
    return (c1.line as number) - (c2.line as number);
  }

  if (c1.rootId !== c2.rootId) {
    if (!c1.rootId) return -1;
    if (!c2.rootId) return 1;
    return c1.rootId > c2.rootId ? 1 : -1;
  }

  if (c1.range && c2.range) {
    const r1 = JSON.stringify(c1.range);
    const r2 = JSON.stringify(c2.range);
    return r1 > r2 ? 1 : -1;
  }
  if (c1.range) return 1;
  if (c2.range) return -1;

  return 0;
}

// TODO: This type should be exposed to gr-diff clients in a separate type file.
// For Gerrit these are instances of GrCommentThread, but other gr-diff users
// have different HTML elements in use for comment threads.
// TODO: Also document the required HTML attributes that thread elements must
// have, e.g. 'diff-side', 'range' (optional), 'line-num'.
// Comment widgets are also required to have `comment-thread` in their css
// class list.
export interface GrDiffThreadElement extends HTMLElement {
  rootId: string;
}

export function isThreadEl(
  node?: Node | EventTarget | null
): node is GrDiffThreadElement {
  return (
    !!node &&
    (node as Node).nodeType === Node.ELEMENT_NODE &&
    (node as Element).classList.contains('comment-thread')
  );
}

/**
 * Simple helper method for creating element classes in the context of
 * gr-diff. This is just a super simple convenience function.
 *
 * TODO: Maybe rename this simple function or inline it everywhere?
 */
export function diffClasses(...additionalClasses: string[]) {
  return additionalClasses.join(' ');
}

/**
 * Simple helper method for creating elements in the context of gr-diff.
 * This is just a super simple convenience function.
 */
export function createElementDiff(
  tagName: string,
  classStr?: string
): HTMLElement {
  const el = document.createElement(tagName);

  if (classStr) {
    for (const className of classStr.split(' ')) {
      el.classList.add(className);
    }
  }
  return el;
}

export function createElementDiffWithText(
  tagName: string,
  textContent: string
) {
  const element = createElementDiff(tagName);
  element.textContent = textContent;
  return element;
}

export function createLineBreak(mode: DiffResponsiveMode) {
  return isResponsive(mode)
    ? createElementDiff('wbr')
    : createElementDiff('span', 'br');
}

/**
 * Returns a <span> element holding a '\t' character, that will visually
 * occupy |tabSize| many columns.
 *
 * @param tabSize The effective size of this tab stop.
 */
export function createTabWrapper(tabSize: number): HTMLElement {
  // Force this to be a number to prevent arbitrary injection.
  const result = createElementDiff('span', 'tab');
  result.setAttribute(
    'style',
    `tab-size: ${tabSize}; -moz-tab-size: ${tabSize};`
  );
  result.innerText = '\t';
  return result;
}

/**
 * Returns a 'div' element containing the supplied |text| as its innerText,
 * with '\t' characters expanded to a width determined by |tabSize|, and the
 * text wrapped at column |lineLimit|, which may be Infinity if no wrapping is
 * desired.
 *
 * @param text The text to be formatted.
 * @param responsiveMode The responsive mode of the diff.
 * @param tabSize The width of each tab stop.
 * @param lineLimit The column after which to wrap lines.
 */
export function formatText(
  text: string,
  responsiveMode: DiffResponsiveMode,
  tabSize: number,
  lineLimit: number,
  elementId: string
): HTMLElement {
  const contentText = createElementDiff('div', 'contentText');
  // <gr-legacy-text> is not defined anywhere, so this behave just as a <div>
  // would. We use this during the migration to lit based diff elements to
  // match <gr-diff-text>. We define a css rule with `display:contents` making
  // sure that this extra element is basically a no-op.
  const legacyText = document.createElement('gr-legacy-text');
  contentText.appendChild(legacyText);
  contentText.id = elementId;
  let columnPos = 0;
  let textOffset = 0;
  for (const segment of text.split(REGEX_TAB_OR_SURROGATE_PAIR)) {
    if (segment) {
      // |segment| contains only normal characters. If |segment| doesn't fit
      // entirely on the current line, append chunks of |segment| followed by
      // line breaks.
      let rowStart = 0;
      let rowEnd = lineLimit - columnPos;
      while (rowEnd < segment.length) {
        legacyText.appendChild(
          document.createTextNode(segment.substring(rowStart, rowEnd))
        );
        legacyText.appendChild(createLineBreak(responsiveMode));
        columnPos = 0;
        rowStart = rowEnd;
        rowEnd += lineLimit;
      }
      // Append the last part of |segment|, which fits on the current line.
      legacyText.appendChild(
        document.createTextNode(segment.substring(rowStart))
      );
      columnPos += segment.length - rowStart;
      textOffset += segment.length;
    }
    if (textOffset < text.length) {
      // Handle the special character at |textOffset|.
      if (text.startsWith('\t', textOffset)) {
        // Append a single '\t' character.
        let effectiveTabSize = tabSize - (columnPos % tabSize);
        if (columnPos + effectiveTabSize > lineLimit) {
          legacyText.appendChild(createLineBreak(responsiveMode));
          columnPos = 0;
          effectiveTabSize = tabSize;
        }
        legacyText.appendChild(createTabWrapper(effectiveTabSize));
        columnPos += effectiveTabSize;
        textOffset++;
      } else {
        // Append a single surrogate pair.
        if (columnPos >= lineLimit) {
          legacyText.appendChild(createLineBreak(responsiveMode));
          columnPos = 0;
        }
        legacyText.appendChild(
          document.createTextNode(text.substring(textOffset, textOffset + 2))
        );
        textOffset += 2;
        columnPos += 1;
      }
    }
  }
  return contentText;
}

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

export function findBlame(blameInfos: BlameInfo[], line?: LineNumber) {
  if (typeof line !== 'number') return undefined;
  return blameInfos.find(info =>
    info.ranges.find(range => range.start <= line && line <= range.end)
  );
}
