import 'jasmine';

import * as crypto from 'crypto';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as ts from 'typescript';

import {Checker} from '../../checker';
import {Failure, fixToString} from '../../failure';
import {AbstractRule} from '../../rule';
import {Config} from '../pattern_config';



/**
 * Turns the provided source (as strings) into a ts.Program. The source files
 * will be named `.../file_${n}.ts`, with n the index of the source file in
 * the `sourceCode` array.
 */
export function compile(...sourceCode: string[]): ts.Program {
  const temporaryFolder = os.tmpdir() + path.sep +
      `tslint_test_input_${crypto.randomBytes(16).toString('hex')}`;
  const fullPaths: string[] = [];
  sourceCode.forEach((s, i) => {
    fullPaths.push(`${temporaryFolder}${path.sep}file_${i}.ts`);
  });

  let error: Error|undefined = undefined;
  let program: ts.Program|undefined = undefined;
  try {  // Wrap it all in a try/finally to clean up the temp files afterwards
    fs.mkdirSync(temporaryFolder);
    sourceCode.forEach((s, i) => {
      fs.writeFileSync(fullPaths[i], s);
    });
    program = ts.createProgram(fullPaths, {});
    if (ts.getPreEmitDiagnostics(program).length !== 0) {
      throw new Error(
          'Your program does not compile cleanly. Diagnostics:\n' +
          ts.formatDiagnostics(
              ts.getPreEmitDiagnostics(program), ts.createCompilerHost({})));
    }
  } catch (e) {
    error = e;
  } finally {
    fullPaths.forEach(p => fs.unlinkSync(p));
    fs.rmdirSync(temporaryFolder);
  }
  if (program && !error) {
    return program;
  } else {
    throw error;
  }
}

function check(rule: AbstractRule, program: ts.Program): Failure[] {
  const checker = new Checker(program);
  rule.register(checker);
  return program.getSourceFiles()
      .map(s => checker.execute(s))
      .reduce((prev, cur) => prev.concat(cur));
}

/** Builds and run the given Rule upon the source files that were provided. */
export function compileAndCheck(
    rule: AbstractRule, ...sourceCode: string[]): Failure[] {
  const program = compile(...sourceCode);
  return check(rule, program);
}

/** Turns a Failure to a fileName. */
export function toFileName(f: Failure) {
  const file = f.toDiagnostic().file;
  return file ? file.fileName : 'unknown';
}

export function getTempDirForWhitelist() {
  // TS uses forward slashes on Windows ¯\_(ツ)_/¯
  return os.platform() == 'win32' ? os.tmpdir().replace(/\\/g, '/') :
                                    os.tmpdir();
}

// Custom matcher for Jasmine, for a better experience matching fixes.
export const customMatchers: jasmine.CustomMatcherFactories = {

  toHaveNFailures(): jasmine.CustomMatcher {
    return {
      compare: (actual: Failure[], expected: Number, config?: Config<any>) => {
        if (actual.length === expected) {
          return {pass: true};
        } else {
          let message =
              `Expected ${expected} Failures, but found ${actual.length}.`;
          if (actual.length) {
            message += '\n' + actual.map(f => f.toString()).join('\n');
          }
          if (config) {
            message += `\nConfig: {kind:${config.kind}, values:${
                JSON.stringify(config.values)}, whitelist:${
                JSON.stringify(config.whitelistEntries)} }`;
          }
          return {pass: false, message};
        }
      }
    };
  },

  toBeFailureMatching(): jasmine.CustomMatcher {
    return {
      compare: (actualFailure: Failure, exp: {
        fileName?: string,
        start?: number,
        end?: number,
        matchedCode?: string,
      }) => {
        const actualDiagnostic = actualFailure.toDiagnostic();
        let regrets = '';
        if (exp === undefined) {
          regrets += 'The matcher requires two arguments. ';
        }
        if (exp.fileName) {
          if (!actualDiagnostic.file) {
            regrets += `Expected diagnostic to have a source file, but it had ${
                actualDiagnostic.file}. `;
          } else if (!actualDiagnostic.file.fileName.endsWith(exp.fileName)) {
            regrets += `Expected ${
                actualDiagnostic.file.fileName} to end with ${exp.fileName}. `;
          }
        }
        if (exp.start !== undefined && actualDiagnostic.start !== exp.start) {
          regrets += expectation('start', exp.start, actualDiagnostic.start);
        }
        if (exp.end !== undefined && actualDiagnostic.end !== exp.end) {
          regrets += expectation('end', exp.end, actualDiagnostic.end);
        }
        if (exp.matchedCode) {
          if (!actualDiagnostic.file) {
            regrets += `Expected diagnostic to have a source file, but it had ${
                actualDiagnostic.file}. `;
          } else if (actualDiagnostic.start === undefined) {
            // I don't know how this could happen, but typings say so.
            regrets += `Expected diagnostic to have a starting position. `;
          } else {
            const foundMatchedCode = actualDiagnostic.file.getFullText().slice(
                Number(actualDiagnostic.start), actualDiagnostic.end);
            if (foundMatchedCode != exp.matchedCode) {
              regrets += `Expected diagnostic to match ${
                  exp.matchedCode}, but was ${foundMatchedCode} (from ${
                  Number(
                      actualDiagnostic.start)} to ${actualDiagnostic.end}). `;
            }
          }
        }
        return {pass: regrets === '', message: regrets};
      }
    };
  },

  /** Checks that a Failure has the expected Fix field. */
  toHaveFixMatching(): jasmine.CustomMatcher {
    return {
      compare: (actualFailure: Failure, exp: [{
                  fileName?: string,
                  start?: number,
                  end?: number,
                  replacement?: string
                }]) => {
        let regrets = '';
        const actualFix = actualFailure.toDiagnostic().fix;
        if (!actualFix) {
          regrets += `Expected ${actualFailure.toString()} to have fix ${
              JSON.stringify(exp)}. `;
        } else if (actualFix.changes.length != exp.length) {
          regrets += `Expected ${exp.length} individual changes, got ${
              actualFix.changes.length}. `;
          if (actualFix.changes.length) {
            regrets += '\n' + fixToString(actualFix);
          }
        } else {
          for (let i = 0; i < exp.length; i++) {
            const e = exp[i];
            const a = actualFix.changes[i];
            if (e.start !== undefined && e.start !== a.start) {
              regrets += expectation(
                  `${i}th individualChange's start`, e.start, a.start);
            }
            if (e.end !== undefined && e.end !== a.end) {
              regrets +=
                  expectation(`${i}th individualChange's end`, e.end, a.end);
            }
            if (e.replacement !== undefined &&
                e.replacement !== a.replacement) {
              regrets += expectation(
                  `${i}th individualChange's replacement`, e.replacement,
                  a.replacement);
            }
            if (e.fileName !== undefined &&
                e.fileName !== a.sourceFile.fileName) {
              regrets += expectation(
                  `${i}th individualChange's fileName`, e.fileName,
                  a.sourceFile.fileName);
            }
            // TODO: Consider adding matchedCode as for the failure matcher.
          }
        }

        return {pass: regrets === '', message: regrets};
      }
    };
  }
};

function expectation(fieldname: string, expectation: any, actual: any) {
  return `Expected .${fieldname} to be ${expectation}, was ${actual}. `;
}

// And the matching type
declare global {
  namespace jasmine {
    interface Matchers<T> {
      toBeFailureMatching(expected: {
        [i: string]: any,  // the rest
        fileName?: string,
        start?: number,
        end?: number,
        matchedCode?: string
      }): void;

      toHaveFixMatching(expected: [
        {fileName?: string, start?: number, end?: number, replacement?: string}
      ]): void;

      toHaveNFailures(expected: Number, config?: Config<any>): void;
    }
  }
}
