// libs
const merge = require('webpack-merge');
const webpack = require('webpack');
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const WebpackBar = require('webpackbar');
const HTMLWebpackPlugin = require('html-webpack-plugin');

const ManifestPlugin = require('webpack-manifest-plugin');
// Forces webpack-dev-server program to write bundle files to the file system.
const WriteFileWebpackPlugin = require('write-file-webpack-plugin');

// Parent package
const package = require('../../../../package.json');

// local
const parts = require('../parts');
const commonConfig = require('../common');
const paths = require('../../paths');

const createConfig = config => {
  const isProduction = config.mode === 'production';
  const isDevelopment = config.mode === 'development';

  return merge([
    // clean in prod
    parts.clean(paths.slsClientBuild, paths.slsBuild),
    {
      mode: config.mode,
      name: 'client',
      target: 'web',
      // Entries configuration
      entry: {
        // bundle is the name used for the files!
        bundle: [paths.main],
      },
      // Source mapping or not
      devtool: isProduction ? 'none' : 'eval-source-map',
    },
    // default
    parts.outputPath({
      path: path.join(paths.slsClientBuild, paths.publicPath),
      // Add a public path
      filename: isProduction ? '[name].[contenthash].js' : '[name].js',
      publicPath: `${config.frontendUrl || '/'}`,
    }),
    parts.loadJavaScript({
      prod: isProduction,
    }),
    parts.loadCSS({
      prod: isProduction,
    }),
    // environment
    parts.setVariables({
      __LOCALE__: config.locale || false,
      __DEV__: config.dev || false,
      __STAGING__: config.staging || false,
      __BROWSER__: true,
      __SSR__: true,
      __TEST__: false,
    }),
    {
      plugins: [
        new CopyPlugin({
          patterns: [
            {
              from: path.join(paths.baseDir, config.staging ? 'static-staging' : 'static'),
              to: path.join(paths.slsClientBuild, paths.publicPath),
              noErrorOnMissing: true,
            },
          ],
        }),
        new HTMLWebpackPlugin({
          template: paths.inAppSrc('index.html'),
        }),
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
        // create a manifes (needed)
        new ManifestPlugin({ fileName: 'manifest.json' }),
        new WebpackBar({
          name: 'client',
        }),
      ],
    },
    isProduction && parts.imageOptimization(),
    isDevelopment && {
      plugins: [
        // Forces webpack-dev-server program to write bundle files to the file system. (even if dev server launched programatically)
        new WriteFileWebpackPlugin(),
      ],
      devServer: {
        compress: true,
        port: config.port || 4000,
        historyApiFallback: true,
        hot: true,
        allowedHosts: ['.lvh.me'],
      },
    },
    parts.optimize(),
  ]);
};

module.exports = (error, params) => {
  const stage = params.stage;

  const config = {
    mode: stage ? 'production' : 'development',
  };

  if (stage === 'production') {
    config.prod = true;
    config.frontendUrl = package.deploy.production.frontendUrl;
  } else if (stage === 'staging') {
    config.staging = true;
    config.frontendUrl = package.deploy.staging.frontendUrl;
  } else if (stage === 'dev') {
    config.dev = true;
    config.frontendUrl = package.deploy.dev.frontendUrl;
  } else {
    config.locale = true;
    // locale development
    config.frontendUrl = package.deploy.locale.frontendUrl;
  }

  const projectConfig = createConfig(config);

  const merged = merge(projectConfig, commonConfig);

  return merged;
};
