import ts from 'typescript';
import tsconfig from 'tsconfig';
import { relative } from 'path';
import Host from './host';

const DEFAULTS = {
  noImplicitAny: false,
  sourceMap: true,
  target: ts.ScriptTarget.ES5,
  module: ts.ModuleKind.CommonJS
};
const FORCED = {
  noEmitOnError: true
};

export default (opts = {}) => (input) => {
  return function buildTypescript (log) {
    return tsconfig.load(process.cwd(), opts.configFile)
      .then((tscfg) => Object.assign({}, DEFAULTS, tscfg.config.compilerOptions, opts.compilerOptions, FORCED))
      .then(convertOpts)
      .then((compilerOpts) => {
        const files = input.map((file) => file.path);
        const host = new Host(input, compilerOpts);
        const program = ts.createProgram(files, compilerOpts, host);
        let results;

        try {
          results = program.emit();
        } catch (e) {
          console.error(e);
        }

        ts.getPreEmitDiagnostics(program)
          .concat(results.diagnostics)
          .forEach((diagnostic) => {
            if (diagnostic.file) {
              let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
              let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
              log(`${relative(process.cwd(), diagnostic.file.fileName)} (${line + 1},${character + 1}): ${message}`);
            }
          });

        return results.emitSkipped ? Promise.reject('emit skipped') : host.emitFiles();
      });
  };
};

function convertOpts (compilerOpts) {
  if (compilerOpts.lib) {
    compilerOpts.lib = compilerOpts.lib.map((lib) => `lib.${lib.toLowerCase()}.d.ts`);
  }
  switch (compilerOpts.moduleResolution) {
    case 'node':
      compilerOpts.moduleResolution = ts.ModuleResolutionKind.NodeJs;
      break;
    case 'classic':
      compilerOpts.moduleResolution = ts.ModuleResolutionKind.Classic;
      break;
  }
  return compilerOpts;
}

@@ -1074,18 +1074,20 @@
         
-le
+cons
 t %7B line
@@ -1181,18 +1181,20 @@
         
-le
+cons
 t messag
@@ -1503,16 +1503,81 @@
       %7D)
+%0A      .catch((err) =%3E log(%60compilation failed: $%7Berr.message%7D%60))
 ;%0A  %7D;%0A%7D
@@ -1773,16 +1773,30 @@
 solution
+.toLowerCase()
 ) %7B%0A    
@@ -1911,16 +1911,16 @@
 assic':%0A
-
       co
@@ -1999,16 +1999,578 @@
 ak;%0A  %7D%0A
+  switch (compilerOpts.target.toLowerCase()) %7B%0A    case 'es5':%0A      compilerOpts.target = ts.ScriptTarget.ES5;%0A      break;%0A    case 'es6':%0A      compilerOpts.target = ts.ScriptTarget.ES5;%0A      break;%0A    case 'es2015':%0A      compilerOpts.target = ts.ScriptTarget.ES2015;%0A      break;%0A    case 'es2016':%0A      compilerOpts.target = ts.ScriptTarget.ES2016;%0A      break;%0A    case 'es2017':%0A      compilerOpts.target = ts.ScriptTarget.ES2017;%0A      break;%0A    case 'esnext':%0A    case 'latest':%0A      compilerOpts.target = ts.ScriptTarget.ESNext;%0A      break;%0A  %7D%0A
   return

transform compilerOptions target