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} 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};
      }
    };
  }
};

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;

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