const webpack = require("webpack");
// const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const { isProduction } = require("../config");
const { getProjectJsGlobals } = require("../utils");
const { getOutputName, getCopySetting } = require("./helpers");
const paths = require("../paths");

let plugins = [
  new webpack.DefinePlugin(
    getProjectJsGlobals().reduce((output, def) => {
      output[def.name] = def.value;
      return output;
    }, {})
  ),
  // new webpack.ProvidePlugin({
  //   Vue: ["vue/dist/vue.esm.js", "default"],
  // }),
  // new CleanWebpackPlugin({
  //   cleanStaleWebpackAssets: true,
  // }),
  new CopyPlugin({
    patterns: [
      getCopySetting("fonts", true),
      getCopySetting("images", false),
      getCopySetting("media", false),
    ],
  }),
  // FIXME: move to favicons-webpack-plugin, it breaks at the moment
  // ].concat(require("./plugins-favicons")());
];

if (isProduction) {
  const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  // FIXME: this breaks with webpack v5?
  const PostCSSAssetsPlugin = require("postcss-assets-webpack-plugin");

  plugins = plugins.concat([
    new MiniCssExtractPlugin({
      filename: getOutputName("entry", "css"),
      chunkFilename: getOutputName("chunk", "css"),
    }),
    // FIXME: this breaks with webpack v5?
    new PostCSSAssetsPlugin({
      test: /\.css$/,
      log: false,
      plugins: [require("postcss-sort-media-queries")()],
    }),
  ]);
} else {
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

if (isProduction) {
  const ImageminPlugin = require("imagemin-webpack-plugin").default;
  const imageminMozjpeg = require("imagemin-mozjpeg");
  const ManifestPlugin = require("webpack-manifest-plugin");
  const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
  const WorkboxPlugin = require("workbox-webpack-plugin");
  // const WebpackBar = require("webpackbar");
  const {
    BUILD_IMG_SKIP_ALL_OPTIMIZATION,
    BUILD_JPEG_COMPRESS,
    BUILD_JPEG_QUALITY,
    BUILD_JPEG_PROGRESSIVE,
  } = process.env;

  if (BUILD_IMG_SKIP_ALL_OPTIMIZATION !== "true") {
    if (BUILD_JPEG_COMPRESS !== "false") {
      plugins.push(
        new ImageminPlugin({
          cacheFolder: paths.join(paths.self.tmp, "imagemin"),
          test: /\.(jpe?g|png|gif|svg)$/i,
          // jpegtran: {
          //   progressive: true
          // },
          plugins: [
            imageminMozjpeg({
              quality: BUILD_JPEG_QUALITY
                ? parseInt(BUILD_JPEG_QUALITY, 10)
                : 100,
              progressive:
                BUILD_JPEG_PROGRESSIVE && BUILD_JPEG_PROGRESSIVE === "false"
                  ? false
                  : true,
            }),
          ],
        })
      );
    }
  }

  plugins = plugins.concat([
    new ManifestPlugin({
      // the public url is prepended in the `assets.blade.php` automated partial
      publicPath: paths.frontend.dest.folders.assets + "/",
      // filter out compiled partials and license files
      filter: ({ name }) => {
        if (name.endsWith(".LICENSE.txt")) {
          return false;
        }
        return true;
      },
      map: (file) => {
        let { name } = file;
        // Problem: hash is contained in the manifest keys, @see open issues
        // https://github.com/danethurber/webpack-manifest-plugin/issues/210
        // https://github.com/danethurber/webpack-manifest-plugin/issues/211
        // so here we manually strip it with a regex
        const matches = name.match(/.+\/.*?\.(.+\.).+$/);
        if (matches && matches[1]) {
          name = name.replace(matches[1], "");
        }

        return {
          ...file,
          name,
        };
      },
    }),
    new OptimizeCssAssetsPlugin({
      cssProcessor: require("cssnano"),
    }),
    new webpack.BannerPlugin({
      banner: require("../utils/banner")(),
      raw: true,
      entryOnly: true,
      exclude: /^vendors/,
    }),
    // @see https://developers.google.com/web/tools/workbox/guides/codelabs/webpack
    // @see https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-webpack-plugin.InjectManifest#InjectManifest
    new WorkboxPlugin.GenerateSW({
      swDest: paths.join(paths.frontend.dest.assets, "service-worker.js"),
      clientsClaim: true,
      skipWaiting: true,
    }),
    // new WebpackBar(),
  ]);
}

if (process.env.DEV_ANALYZE === "true") {
  const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
    .BundleAnalyzerPlugin;
  plugins = plugins.concat([
    new BundleAnalyzerPlugin({
      reportFilename: paths.join(
        paths.frontend.dest.folders.assets,
        "stats.json"
      ),
    }),
  ]);
}

module.exports = () => plugins;
