/* eslint-disable @typescript-eslint/camelcase */
/* eslint-disable @typescript-eslint/no-var-requires */
// Copyright 2017-2019 @polkadot/apps authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

const fs = require('fs');
const path = require('path');
const webpack = require('webpack');

const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { WebpackPluginServe } = require('webpack-plugin-serve');

const findPackages = require('../../scripts/findPackages'); // Do we need to add joy- apps in that script?

const DEFAULT_THEME = 'substrate';
const ENV = process.env.NODE_ENV || 'development';

function createWebpack ({ alias = {}, context, name = 'index' }) {
  const pkgJson = require(path.join(context, 'package.json'));
  const isProd = ENV === 'production';
  const hasPublic = fs.existsSync(path.join(context, 'public'));
  const plugins = hasPublic
    ? [new CopyWebpackPlugin([{ from: 'public' }])]
    : [];
  // disabled, smooths dev load, was -
  // isProd ? 'source-map' : 'cheap-eval-source-map',
  const devtool = false;

  return {
    context,
    devtool,
    entry: [
      '@babel/polyfill',
      `./src/${name}.tsx`,
      isProd
        ? null
        : null // 'webpack-plugin-serve/client'
    ].filter((entry) => entry),
    mode: ENV,
    output: {
      chunkFilename: '[name].[chunkhash:8].js',
      filename: '[name].[hash:8].js',
      globalObject: '(typeof self !== \'undefined\' ? self : this)',
      path: path.join(context, 'build')
    },
    resolve: {
      alias,
      extensions: ['.js', '.jsx', '.ts', '.tsx']
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          exclude: /(node_modules)/,
          use: [
            isProd
              ? MiniCssExtractPlugin.loader
              : require.resolve('style-loader'),
            {
              loader: require.resolve('css-loader'),
              options: {
                importLoaders: 1
              }
            },
            {
              loader: require.resolve('postcss-loader'),
              options: {
                ident: 'postcss',
                plugins: () => [
                  require('precss'),
                  require('autoprefixer'),
                  require('postcss-simple-vars'),
                  require('postcss-nested'),
                  require('postcss-import'),
                  require('postcss-clean')(),
                  require('postcss-flexbugs-fixes')
                ]
              }
            }
          ]
        },
        {
          test: /\.s[ac]ss$/i,
          use: [
            // Creates `style` nodes from JS strings
            'style-loader',
            // Translates CSS into CommonJS
            'css-loader',
            // Compiles Sass to CSS
            'sass-loader'
          ]
        },
        {
          test: /\.less$/,
          loaders: ['style-loader', 'css-loader', 'less-loader']
        },
        {
          test: /\.css$/,
          include: /node_modules/,
          use: [
            isProd
              ? MiniCssExtractPlugin.loader
              : require.resolve('style-loader'),
            require.resolve('css-loader')
          ]
        },
        {
          test: /\.(js|ts|tsx)$/,
          exclude: /(node_modules)/,
          use: [
            require.resolve('thread-loader'),
            {
              loader: require.resolve('babel-loader'),
              options: require('@polkadot/dev-react/config/babel')
            }
          ]
        },
        {
          test: /\.md$/,
          use: [
            require.resolve('html-loader'),
            require.resolve('markdown-loader')
          ]
        },
        {
          test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
          use: [
            {
              loader: require.resolve('url-loader'),
              options: {
                limit: 10000,
                name: 'static/[name].[hash:8].[ext]'
              }
            }
          ]
        },
        {
          test: [/\.eot$/, /\.ttf$/, /\.svg$/, /\.woff$/, /\.woff2$/],
          use: [
            {
              loader: require.resolve('file-loader'),
              options: {
                name: 'static/[name].[hash:8].[ext]'
              }
            }
          ]
        }
      ]
    },
    node: {
      child_process: 'empty',
      dgram: 'empty',
      fs: 'empty',
      net: 'empty',
      tls: 'empty'
    },
    optimization: {
      runtimeChunk: 'single',
      splitChunks: {
        cacheGroups: {
          vendorOther: {
            chunks: 'initial',
            enforce: true,
            name: 'vendor',
            test: /node_modules\/(asn1|bn\.js|buffer|cuint|elliptic|lodash|moment|readable-stream|rxjs)/
          },
          vendorReact: {
            chunks: 'initial',
            enforce: true,
            name: 'react',
            test: /node_modules\/(chart|i18next|react|semantic-ui)/
          },
          polkadotJs: {
            chunks: 'initial',
            enforce: true,
            name: 'polkadotjs',
            test: /node_modules\/(@polkadot\/wasm-(crypto|dalek-ed25519|schnorrkel))/
          }
        }
      }
    },
    performance: {
      hints: false
    },
    plugins: plugins.concat([
      new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: JSON.stringify(ENV),
          VERSION: JSON.stringify(pkgJson.version),
          UI_MODE: JSON.stringify(process.env.UI_MODE || 'light'),
          UI_THEME: JSON.stringify(process.env.UI_THEME || DEFAULT_THEME),
          WS_URL: JSON.stringify(process.env.WS_URL)
        }
      }),
      new HtmlWebpackPlugin({
        inject: true,
        template: path.join(context, `${hasPublic ? 'public/' : ''}${name}.html`),
        IS_PROD: isProd,
        PAGE_TITLE: process.env.UI_THEME === 'substrate'
          ? 'Joystream Network Portal'
          : 'Joystream Network Portal'
      }),
      new webpack.optimize.SplitChunksPlugin(),
      new MiniCssExtractPlugin({
        filename: '[name].[contenthash:8].css'
      }),
      isProd
        ? null
        : new WebpackPluginServe({
          hmr: false, // switch off, Chrome WASM memory leak
          liveReload: false, // explict off, overrides hmr
          progress: false, // since we have hmr off, disable
          port: 3000,
          static: path.join(process.cwd(), '/build')
        })
    ]).filter((plugin) => plugin),
    watch: !isProd
  };
}

module.exports = createWebpack({
  context: __dirname,
  alias: {
    ...(
      findPackages().reduce((alias, { dir, name }) => {
        alias[name] = path.resolve(__dirname, `../${dir}/src`);

        return alias;
      }, {})
    ),
    // TODO: Me might try to add it to "findPackages", but this will be a little more tricky
    '@joystream/types': path.resolve(__dirname, '../../../types/src')
  }
});
