require('dotenv').config();

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const DotenvPlugin = require('dotenv-webpack');
const merge = require('webpack-merge');

const targetDir = path.normalize(path.join(__dirname, 'dist'));

if (! process.env.NODE_ENV) {
  console.error('Please set NODE_ENV');
  process.exit(1);
}

const babelOpts = {
  presets: [
    '@babel/preset-env',
  ],
};

const tsconfig = require('./tsconfig.json');
const pathAliases = Object.entries(tsconfig.compilerOptions.paths || []).reduce((aliases, pair) => {
  let alias = pair[0];
  if (alias.endsWith('/*')) alias = alias.slice(0, -2);

  let aliasPath = pair[1][0];
  if (aliasPath.endsWith('/*')) aliasPath = aliasPath.slice(0, -2);

  aliases[alias] = path.resolve(__dirname, aliasPath);
  return aliases;
}, {});

let config = {
  entry: './src/main.ts',
  output: {
    filename: '[name].[hash].js',
    path: targetDir,
    publicPath: '/',
  },
  module: {
    rules: [
      // Vue / Babel / Typescript
      {
        test: /\.vue$/,
        use: ["vue-loader"],
      },
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: babelOpts,
          },
          {
            loader: 'ts-loader',
            options: {
              appendTsSuffixTo: [/\.vue$/],
            },
          },
        ],
      },
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: babelOpts,
        },
      },
      {
        test: /\.js$/,
        use: ["source-map-loader"],
        enforce: "pre",
      },

      // Stylesheets
      {
        test: /\.p?css$/,
        use: [
          "vue-style-loader",
          {
            loader: "css-loader",
            options: {
              importLoaders: 1,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              ident: "postcss",
              plugins: loader => {
                const plugins = [
                  require('postcss-import')({
                    resolve(id, base, options) {
                      // Since WebStorm doesn't resolve imports from node_modules without a tilde (~) prefix,
                      // strip the tilde here to get the best of both worlds (webstorm support + postcss-import support)
                      if (id[0] === '~') id = id.slice(1);
                      // Call the original resolver after stripping the tilde
                      return require('postcss-import/lib/resolve-id')(id, base, options);
                    },
                  }),
                  require('postcss-nesting')(),
                  require('tailwindcss')(),
                ];

                if (process.env.NODE_ENV === "production") {
                  plugins.push(
                    require('postcss-preset-env')(),
                    require('cssnano')(),
                  );
                }

                return plugins;
              },
            },
          },
        ],
      },

      // Images/files
      {
        test: /\.(png|jpg)$/i,
        use: {
          loader: "file-loader",
          options: {
            name: "[name]-[hash].[ext]",
          },
        },
      },

      // HTML
      {
        test: /\.html$/,
        use: [
          {
            loader: "html-loader",
            options: {
              root: path.resolve(__dirname, 'src'),
              attrs: ['img:src', 'link:href'],
              ...(process.env.NODE_ENV === 'production' && {
                minimize: true,
                removeComments: true,
                collapseWhitespace: true,
              }),
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      template: 'src/index.html',
      files: {
        "css": ["./src/style/initial.pcss"],
        "js": ["./src/main.ts"],
      },
    }),
    new DotenvPlugin(),
  ],
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.mjs', '.vue'],
    alias: pathAliases,
  },
};

if (process.env.NODE_ENV === 'production') {
  config = merge(config, {
    mode: 'production',
    devtool: 'source-map',
  });
} else {
  config = merge(config, {
    mode: 'development',
    devtool: 'eval',
    devServer: {
      ...(process.env.DEV_HOST ? { host: process.env.DEV_HOST } : undefined),
      historyApiFallback: true,
      port: 1234,
    },
  });
}

module.exports = config;