const path = require('path');
const webpack = require('webpack');
const LoadablePlugin = require('@loadable/webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const { rootDir, target, env, version, staticPath } = require('../helpers/const');

module.exports = {
  context: rootDir,

  name: `client-${target}`,
  mode: 'production',
  target: 'browserslist',

  devtool: 'hidden-source-map',

  entry: {
    main: path.resolve(rootDir, './src/application/client/main.tsx')
  },

  output: {
    path: path.resolve(rootDir, './build/client', target),
    filename: '[name].[contenthash:8].js',
    chunkFilename: 'chunks/[id].[contenthash:8].js',
    assetModuleFilename: '[contenthash:8][ext]',
    publicPath: `${staticPath}/${target}/`
  },

  cache: {
    type: 'filesystem',
    buildDependencies: {
      configs: [__filename, path.resolve(rootDir, '.browserslistrc'), path.resolve(__dirname, '../../babel.config.js')]
    }
  },

  optimization: {
    runtimeChunk: false,
    splitChunks: {
      hidePathInfo: true
    },
    minimizer: ['...', new CssMinimizerPlugin()]
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
    alias: {
      '@root': path.resolve(rootDir, './'),
      '@game': path.resolve(rootDir, './src'),
      '@server': path.resolve(rootDir, '../game-server/src'),
      '@api': path.resolve(rootDir, '../game-api/src'),
      '@map': path.resolve(rootDir, '../map/src'),
      '@core': path.resolve(rootDir, '../core/src'),

      '_service': path.resolve(rootDir, './src'),
      '_build': path.resolve(rootDir, './build'),

      'react': path.resolve(rootDir, './node_modules/react'),
      'react-dom': path.resolve(rootDir, './node_modules/react-dom'),
      '@loadable': path.resolve(rootDir, './node_modules/@loadable'),
      '@babel': path.resolve(rootDir, './node_modules/@babel'),
      'svg-sprite-loader': path.resolve(rootDir, './node_modules/svg-sprite-loader'),
      'events': path.resolve(rootDir, './node_modules/events'),
    },
    fallback: {
      'crypto': false,
      'path': false,
      'util': false
    }
  },

  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
    'url': 'window',
    'util': 'window',
  },

  module: {
    generator: {
      'asset': {
        publicPath: staticPath,
        outputPath: './'
      },
      'asset/resource': {
        publicPath: staticPath,
        outputPath: './'
      }
    },

    rules: [
      // JavaScript
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
        type: 'javascript/auto'
      },
      // TypeScript
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      // CSS, Sass and PostCSS
      {
        test: /\.(?:s[ac]|c)ss$/,
        use: [
          // Creates `style` nodes from JS strings
          MiniCssExtractPlugin.loader,
          // Translates CSS into CommonJS
          'css-loader',
          {
            // PostCSS modifications
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                config: `${rootDir}/postcss.config.js`
              }
            }
          },
          'sass-loader'
        ]
      },
      // Images
      {
        test: /\.(?:ico|gif|png|jpg|jpeg|svg)$/i,
        type: 'asset/resource'
      },
      {
        test: /\.svg$/,
        issuer: /\.(?:s[ac]|c)ss$/,
        type: 'asset',
        use: ['svgo-loader']
      }
    ]
  },

  plugins: [
    new webpack.EnvironmentPlugin({
      NODE_ENV: env,
      STATIC_PATH: staticPath,
      APP_VERSION: version,
      PLATFORM: 'client',
      TARGET: target,
      API_HOST: 'localhost:3001',
      SERVER_MSGPACK: 0,
    }),

    new LoadablePlugin({
      writeToDisk: true
    }),

    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:8].css',
      chunkFilename: 'chunks/[id].[contenthash:8].css',
      ignoreOrder: true
    })
  ].filter(Boolean)
};
