/**
 * @fileoverview extensions to TypeScript functionality around error handling
 * (ts.Diagnostics).
 */

import * as ts from 'typescript';

import {BazelOptions} from './tsconfig';

/**
 * If the current compilation was a compilation test expecting certain
 * diagnostics, filter out the expected diagnostics, and add new diagnostics
 * (aka errors) for non-matched diagnostics.
 */
export function filterExpected(
    bazelOpts: BazelOptions, diagnostics: ts.Diagnostic[],
    formatFn = uglyFormat): ts.Diagnostic[] {
  if (!bazelOpts.expectedDiagnostics.length) return diagnostics;

  // The regex contains two parts:
  // 1. Optional position: '\(5,1\)'
  // 2. Required TS error: 'TS2000: message text.'
  // Need triple escapes because the expected diagnostics that we're matching
  // here are regexes, too.
  const ERROR_RE = /^(?:\\\((\d*),(\d*)\\\).*)?TS(\d+):(.*)/;
  const incorrectErrors =
      bazelOpts.expectedDiagnostics.filter(e => !e.match(ERROR_RE));
  if (incorrectErrors.length) {
    const msg = `Expected errors must match regex ${ERROR_RE}\n\t` +
        `expected errors are "${incorrectErrors.join(', ')}"`;
    return [{
      file: undefined!,
      start: 0,
      length: 0,
      messageText: msg,
      category: ts.DiagnosticCategory.Error,
      code: 0,
    }];
  }

  // ExpectedDiagnostics represents the "expected_diagnostics" users provide in
  // the BUILD file. It is used for easier comparsion with the actual
  // diagnostics.
  interface ExpectedDiagnostics {
    line: number;
    column: number;
    expected: string;
    code: number;
    regexp: RegExp;
    matched: boolean;
  }

  const expectedDiags: ExpectedDiagnostics[] =
      bazelOpts.expectedDiagnostics.map(expected => {
        const m = expected.match(/^(?:\\\((\d*),(\d*)\\\).*)?TS(\d+):(.*)$/);
        if (!m) {
          throw new Error(
              'Incorrect expected error, did you forget character escapes in ' +
              expected);
        }
        const [, lineStr, columnStr, codeStr, regexp] = m;
        const [line, column, code] = [lineStr, columnStr, codeStr].map(str => {
          const i = Number(str);
          if (Number.isNaN(i)) {
            return 0;
          }
          return i;
        });
        return {
          line,
          column,
          expected,
          code,
          regexp: new RegExp(regexp),
          matched: false,
        };
      });

  const unmatchedDiags = diagnostics.filter(diag => {
    let line = -1;
    let character = -1;
    if (diag.file && diag.start) {
      ({line, character} =
           ts.getLineAndCharacterOfPosition(diag.file, diag.start));
    }
    let matched = false;
    const msg = formatFn(bazelOpts.target, [diag]);
    // checkDiagMatchesExpected checks if the expected diagnostics matches the
    // actual diagnostics.
    const checkDiagMatchesExpected =
        (expDiag: ExpectedDiagnostics, diag: ts.Diagnostic) => {
          if (expDiag.code !== diag.code || msg.search(expDiag.regexp) === -1) {
            return false;
          }
          // line and column are optional fields, only check them if they
          // are explicitly specified.
          // line and character are zero based.
          if (expDiag.line !== 0 && expDiag.line !== line + 1) {
            return false;
          }
          if (expDiag.column !== 0 && expDiag.column !== character + 1) {
            return false;
          }
          return true;
        };

    for (const expDiag of expectedDiags) {
      if (checkDiagMatchesExpected(expDiag, diag)) {
        expDiag.matched = true;
        matched = true;
        // continue, one diagnostic may match multiple expected errors.
      }
    }
    return !matched;
  });

  const unmatchedErrors = expectedDiags.filter(err => !err.matched).map(err => {
    const file = ts.createSourceFile(
        bazelOpts.target, '/* fake source as marker */',
        ts.ScriptTarget.Latest);
    const messageText =
        `Expected a compilation error matching ${JSON.stringify(err.expected)}`;
    return {
      file,
      start: 0,
      length: 0,
      messageText,
      category: ts.DiagnosticCategory.Error,
      code: err.code,
    };
  });

  return unmatchedDiags.concat(unmatchedErrors);
}

/**
 * Formats the given diagnostics, without pretty printing.  Without colors, it's
 * better for matching against programmatically.
 * @param target The bazel target, e.g. //my/package:target
 */
export function uglyFormat(
    target: string, diagnostics: ReadonlyArray<ts.Diagnostic>): string {
  const diagnosticsHost: ts.FormatDiagnosticsHost = {
    getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
    getNewLine: () => ts.sys.newLine,
    // Print filenames including their relativeRoot, so they can be located on
    // disk
    getCanonicalFileName: (f: string) => f
  };
  return ts.formatDiagnostics(diagnostics, diagnosticsHost);
}

/**
 * Pretty formats the given diagnostics (matching the --pretty tsc flag).
 * @param target The bazel target, e.g. //my/package:target
 */
export function format(
    target: string, diagnostics: ReadonlyArray<ts.Diagnostic>): string {
  const diagnosticsHost: ts.FormatDiagnosticsHost = {
    getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
    getNewLine: () => ts.sys.newLine,
    // Print filenames including their relativeRoot, so they can be located on
    // disk
    getCanonicalFileName: (f: string) => f
  };
  return ts.formatDiagnosticsWithColorAndContext(diagnostics, diagnosticsHost);
}
