const { existsSync } = require('fs');
const { join } = require('path');
const { Mixin } = require('hops-mixin');
// eslint-disable-next-line node/no-unpublished-require
const chalk = require('chalk');

const getCompilerOptions = (ts, rootPath) => {
  const parseConfigHost = {
    fileExists: ts.sys.fileExists,
    readFile: ts.sys.readFile,
    readDirectory: ts.sys.readDirectory,
    useCaseSensitiveFileNames: true,
  };
  const configFileName = ts.findConfigFile(
    rootPath,
    ts.sys.fileExists,
    'tsconfig.json'
  );
  const { config } = ts.readConfigFile(configFileName, ts.sys.readFile);
  const { options } = ts.parseJsonConfigFileContent(
    config,
    parseConfigHost,
    rootPath
  );

  return options;
};

class TypescriptMixin extends Mixin {
  configureBuild(webpackConfig, { jsLoaderConfig, allLoaderConfigs }, target) {
    const { loader, options, exclude } = jsLoaderConfig;
    const isDevelop =
      target === 'develop' ||
      (target === 'node' && process.env.NODE_ENV !== 'production');
    const loaderOptions = isDevelop
      ? { compilerOptions: { isolatedModules: true }, transpileOnly: true }
      : undefined;

    allLoaderConfigs.unshift({
      test: /\.tsx?$/,
      exclude,
      use: [
        {
          loader,
          options,
        },
        {
          loader: require.resolve('ts-loader'),
          options: loaderOptions,
        },
      ],
    });
    webpackConfig.resolve.extensions.push('.ts', '.tsx');
  }

  diagnose() {
    let ts;
    try {
      ts = require('typescript');
    } catch (e) {
      return;
    }
    const { rootDir } = this.config;
    const tsConfigPath = join(rootDir, 'tsconfig.json');

    if (!existsSync(tsConfigPath)) {
      const tsConfigContent = JSON.stringify(
        {
          extends: 'hops-typescript/tsconfig.json',
        },
        null,
        2
      );

      return chalk`
{red No "tsconfig.json" file found in your project root directory ("${rootDir}").}
{red To get started, create a "tsconfig.json" file in your project's root with the following content:}
{cyan ${tsConfigContent}}
`;
    }

    const compilerOptions = getCompilerOptions(ts, rootDir);
    const properties = {
      target: ts.ScriptTarget.ESNext,
      moduleResolution: ts.ModuleResolutionKind.NodeJs,
      jsx: ts.JsxEmit.Preserve,
    };

    for (let [property, value] of Object.entries(properties)) {
      if (compilerOptions[property] !== value) {
        return chalk.red(
          `Please do not overwrite the value "compilerOptions.${property}" in your "tsconfig.json", otherwise Hops will not work as expected.`
        );
      }
    }
  }
}

module.exports = TypescriptMixin;

@@ -855,16 +855,924 @@
 const %7B 
+experimentalEsbuild %7D = this.options;%0A%0A    webpackConfig.resolve.extensions.push('.ts', '.tsx');%0A%0A    if (experimentalEsbuild) %7B%0A      const %7B%0A        include,%0A        exclude,%0A        use: %5B%7B loader, options %7D, ...loaders%5D,%0A      %7D = jsLoaderConfig;%0A%0A      allLoaderConfigs.unshift(%0A        %7B%0A          test: /%5C.ts$/,%0A          include,%0A          exclude,%0A          use: %5B%0A            %7B%0A              loader,%0A              options: %7B%0A                ...options,%0A                loader: 'ts',%0A              %7D,%0A            %7D,%0A            ...loaders,%0A          %5D,%0A        %7D,%0A        %7B%0A          test: /%5C.tsx$/,%0A          include,%0A          exclude,%0A          use: %5B%0A            %7B%0A              loader,%0A              options: %7B%0A                ...options,%0A                loader: 'tsx',%0A              %7D,%0A            %7D,%0A            ...loaders,%0A          %5D,%0A        %7D%0A      );%0A    %7D else %7B%0A      const %7B exclude, 
 loader, 
@@ -1782,17 +1782,8 @@
 ions
-, exclude
  %7D =
@@ -1795,24 +1795,27 @@
 aderConfig;%0A
+%0A  
     const is
@@ -1826,24 +1826,26 @@
 lop =%0A      
+ 
+ 
 target === '
@@ -1856,16 +1856,18 @@
 lop' %7C%7C%0A
+  
       (t
@@ -1922,24 +1922,26 @@
 oduction');%0A
+  
     const lo
@@ -1970,16 +1970,18 @@
 p%0A      
+  
 ? %7B comp
@@ -2042,16 +2042,18 @@
  true %7D%0A
+  
       : 
@@ -2064,24 +2064,26 @@
 fined;%0A%0A    
+  
 allLoaderCon
@@ -2097,16 +2097,18 @@
 shift(%7B%0A
+  
       te
@@ -2124,24 +2124,26 @@
 x?$/,%0A      
+  
 exclude,%0A   
@@ -2135,24 +2135,26 @@
    exclude,%0A
+  
       use: %5B
@@ -2154,34 +2154,38 @@
  use: %5B%0A        
-%7B%0A
+  %7B%0A  
           loader
@@ -2192,24 +2192,26 @@
 ,%0A          
+  
 options,%0A   
@@ -2199,32 +2199,34 @@
        options,%0A
+  
         %7D,%0A     
@@ -2220,34 +2220,38 @@
      %7D,%0A        
-%7B%0A
+  %7B%0A  
           loader
@@ -2284,32 +2284,34 @@
 er'),%0A          
+  
 options: loaderO
@@ -2310,32 +2310,34 @@
  loaderOptions,%0A
+  
         %7D,%0A     
@@ -2333,27 +2333,31 @@
    %7D,%0A      
+  
 %5D,%0A
+  
     %7D);%0A    
@@ -2360,60 +2360,88 @@
     
-webpackConfig.resolve.extensions.push('.ts', '.tsx')
+%7D%0A  %7D%0A%0A  handleArguments(argv) %7B%0A    this.options = %7B ...this.options, ...argv %7D
 ;%0A  

add support for esbuild