//
// Copyright © 2023 Hardcore Engineering Inc.
//

const Dotenv = require('dotenv-webpack')
const path = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
const DefinePlugin = require('webpack').DefinePlugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')

const mode = process.env.NODE_ENV || 'development'
const prod = mode === 'production'
const dev = (process.env.CLIENT_TYPE ?? '') === 'dev' || mode === 'development'
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
console.log('mode', mode)
const { EsbuildPlugin } = require('esbuild-loader')

const doValidate = !prod || (process.env.DO_VALIDATE === 'true')

/**
 * @type {Configuration}
 */
module.exports = [
  {
    mode: dev ? 'development' : mode,
    entry: {
      serviceWorker: '@hcengineering/notification/src/serviceWorker.ts'
    },
    module: {
      rules: [
        {
          test: /\.ts$/,
          exclude: /(node_modules|\.webpack)/,
          use: {
            loader: 'esbuild-loader',
            options: {
              target: 'es2021',
              keepNames: true,
              minify: !prod,
              sourcemap: !prod
            }
          }
        }
      ]
    },
    output: {
      path: __dirname + '/dist',
      filename: '[name].js',
      chunkFilename: '[name].js',
      publicPath: '/',
      pathinfo: false
    },
    resolve: {
      extensions: ['.ts', '.js'],
      conditionNames: ['svelte', 'browser', 'import']
    }
  },
  {
    mode: dev ? 'development' : mode,
    entry: {
      electron: './src/main/start.ts',
      preload: './src/ui/preload.ts'
    },
    target: 'electron-main',
    plugins: [
      ...(doValidate ? [new ForkTsCheckerWebpackPlugin()] : []),
      new Dotenv({ path: prod ? '.env' : '.env-dev' }),
      new DefinePlugin({
        'process.env.MODEL_VERSION': JSON.stringify(process.env.MODEL_VERSION),
        'process.env.VERSION': JSON.stringify(process.env.VERSION)
      })
    ],
    module: {
      rules: [
        // Add support for native node modules
        {
          // We're specifying native_modules in the test because the asset relocator loader generates a
          // "fake" .node file which is really a cjs file.
          test: /native_modules[/\\].+\.node$/,
          use: 'node-loader'
        },
        {
          test: /[/\\]node_modules[/\\].+\.(m?js|node)$/,
          parser: { amd: false },
          use: {
            loader: '@vercel/webpack-asset-relocator-loader',
            options: {
              outputAssetBase: 'native_modules'
            }
          }
        },
        {
          test: /\.ts$/,
          exclude: /(node_modules|\.webpack)/,
          use: {
            loader: 'esbuild-loader',
            options: {
              target: 'es2021',
              keepNames: true,
              minify: !prod,
              sourcemap: !prod
            }
          }
        }
      ]
    },
    output: {
      globalObject: 'this',
      path: path.join(__dirname, '/dist/main/'),
      publicPath: '',
      clean: true
    },
    resolve: {
      extensions: ['.ts', '.js'],
      conditionNames: ['svelte', 'browser', 'import']
    }
  },

  // ------ UI Part --------------------------
  {
    entry: {
      bundle: ['@hcengineering/theme/styles/global.scss', ...['./src/ui/index.ts']]
    },
    ignoreWarnings: [
      {
        message: /a11y-/
      },
      /warning from compiler/,
      (warning) => true
    ],
    resolve: {
      symlinks: true,
      alias: {
        svelte: path.resolve('node_modules', 'svelte/src/runtime'),
        '@hcengineering/platform-rig/profiles/ui/svelte': path.resolve('node_modules', 'svelte/src/runtime')
      },
      fallback: {
        crypto: false,
        path: false,
        fs: false
      },
      extensions: ['.mjs', '.js', '.svelte', '.ts'],
      conditionNames: ['svelte', 'browser', 'import']
    },
    output: {
      path: path.join(__dirname, '/dist/ui/'),
      filename: 'bundle.js',
      publicPath: '',
      chunkFormat: false,
      clean: true
    },
    optimization: prod
      ? {
          minimize: true,
          minimizer: [
            new EsbuildPlugin({
              target: 'es2021',
              keepNames: true,
              minify: !prod,
              sourcemap: !prod
            })
          ]
        }
      : {},
    module: {
      rules: [
        {
          test: /\.ts?$/,
          loader: 'esbuild-loader',
          options: {
            target: 'es2021',
            keepNames: true,
            minify: !prod,
            sourcemap: !prod
          },
          exclude: /node_modules/
        },
        {
          test: /\.svelte$/,
          use: {
            loader: 'svelte-loader',
            options: {
              compilerOptions: {
                dev
              },
              emitCss: true,
              hotReload: dev,
              preprocess: require('svelte-preprocess')({
                postcss: true,
                sourceMap: dev
              }),
              hotOptions: {
                // Prevent preserving local component state
                preserveLocalState: true,

                // If this string appears anywhere in your component's code, then local
                // state won't be preserved, even when noPreserveState is false
                noPreserveStateKey: '@!hmr',

                // Prevent doing a full reload on next HMR update after fatal error
                noReload: true,

                // Try to recover after runtime errors in component init
                optimistic: false,

                // --- Advanced ---

                // Prevent adding an HMR accept handler to components with
                // accessors option to true, or to components with named exports
                // (from <script context="module">). This have the effect of
                // recreating the consumer of those components, instead of the
                // component themselves, on HMR updates. This might be needed to
                // reflect changes to accessors / named exports in the parents,
                // depending on how you use them.
                acceptAccessors: true,
                acceptNamedExports: true
              }
            }
          }
        },

        {
          // required to prevent errors from Svelte on Webpack 5+, omit on Webpack 4
          test: /node_modules\/svelte\/.*\.mjs$/,
          resolve: {
            fullySpecified: false
          }
        },

        {
          test: /\.css$/,
          use: [
            // prod ? MiniCssExtractPlugin.loader :
            'style-loader',
            'css-loader',
            'postcss-loader'
          ]
        },

        {
          test: /\.scss$/,
          use: [
            // prod ? MiniCssExtractPlugin.loader :
            'style-loader',
            'css-loader',
            'postcss-loader',
            'sass-loader'
          ]
        },

        {
          test: /\.(ttf|otf|eot|woff|woff2)$/,
          use: {
            loader: 'file-loader',
            options: {
              name: 'fonts/[hash:base64:8].[ext]',
              esModule: false
            }
          }
        },
        {
          test: /\.(wav|ogg)$/,
          use: {
            loader: 'file-loader',
            options: {
              'name': 'snd/[contenthash].[ext]',
              esModule: false
            }
          }
        },
        {
          test: /\.(jpg|png|webp|heic|avif)$/,
          use: {
            loader: 'file-loader',
            options: {
              name: 'img/[hash:base64:8].[ext]',
              esModule: false
            }
          }
        },
        {
          test: /\.svg$/,
          use: [
            {
              loader: 'file-loader',
              options: {
                name: 'img/[hash:base64:8].[ext]',
                esModule: false
              }
            },
            {
              loader: 'svgo-loader',
              options: {
                plugins: [
                  { name: 'removeHiddenElems', active: false }
                  // { removeHiddenElems: { displayNone: false } },
                  // { cleanupIDs: false },
                  // { removeTitle: true }
                ]
              }
            }
          ]
        }
      ]
    },
    mode: dev ? 'development' : mode,
    plugins: [
      new CopyPlugin({
        patterns: [{ from: 'public', to: 'public' }]
      }),
      new HtmlWebpackPlugin({
        template: './src/ui/index.ejs',
        meta: {
          viewport: 'width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=1'
        },
        publicPath: ''
      }),
      ...(!dev ? [new CompressionPlugin()] : []),
      // new MiniCssExtractPlugin({
      //   filename: '[name].[id][contenthash].css'
      // }),
      new Dotenv({ path: prod ? '.env' : '.env-dev' }),
      new DefinePlugin({
        'process.env.CLIENT_TYPE': JSON.stringify(process.env.CLIENT_TYPE)
      }),
      ...(doValidate
        ? [
            new ForkTsCheckerWebpackPlugin()
          ]
        : [])
    ],
    watchOptions: {
      // for some systems, watching many files can result in a lot of CPU or memory usage
      // https://webpack.js.org/configuration/watch/#watchoptionsignored
      // don't use this pattern, if you have a monorepo with linked packages
      ignored: /node_modules/,
      aggregateTimeout: 500,
      poll: 1000
    },
    devtool: !dev ? false : 'eval-source-map'
  }
]