'use strict';
const fs = require('fs');
const glob = require('glob');
const path = require('path');
const webpack = require('webpack');
const CleanPlugin = require('clean-webpack-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
const HtmlInlineSourcePlugin = require('html-webpack-inline-source-plugin');
const HtmlPlugin = require('html-webpack-plugin');
const ImageminPlugin = require('imagemin-webpack-plugin').default;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// const SizePlugin = require('size-plugin');
const TerserPlugin = require('terser-webpack-plugin');
// const WebpackDeepScopeAnalysisPlugin = require('webpack-deep-scope-plugin').default;

module.exports = function(env, argv) {
    env = env || {};
    env.production = Boolean(env.production);
    env.optimizeImages = env.production || Boolean(env.optimizeImages);
    env.copyClipboardyFallbacks = env.production || Boolean(env.copyClipboardyFallbacks);

    if (!env.optimizeImages && !fs.existsSync(path.resolve(__dirname, 'images/settings'))) {
        env.optimizeImages = true;
    }

    if (!env.copyClipboardyFallbacks && !fs.existsSync(path.resolve(__dirname, 'fallbacks'))) {
        env.copyClipboardyFallbacks = true;
    }

    return [getExtensionConfig(env), getUIConfig(env)];
};

function getExtensionConfig(env) {
    const clean = ['dist'];
    if (env.copyClipboardyFallbacks) {
        clean.push('fallbacks');
    }

    const plugins = [
        // https://github.com/GoogleChromeLabs/size-plugin/issues/12
        // new SizePlugin(),
        new CleanPlugin(clean, { verbose: false }),
        new webpack.IgnorePlugin(/^spawn-sync$/)
    ];

    if (env.copyClipboardyFallbacks) {
        plugins.push(
            // @ts-ignore
            new FileManagerPlugin({
                onEnd: [
                    {
                        copy: [
                            {
                                source: path.resolve(__dirname, 'node_modules/clipboardy/fallbacks'),
                                destination: 'fallbacks/'
                            }
                        ]
                    }
                ]
            })
        );
    }

    // if (env.production) {
    // plugins.push(new WebpackDeepScopeAnalysisPlugin());
    // }

    return {
        name: 'extension',
        entry: './src/extension.ts',
        mode: env.production ? 'production' : 'development',
        target: 'node',
        node: {
            __dirname: false
        },
        devtool: !env.production ? 'source-map' : undefined,
        output: {
            libraryTarget: 'commonjs2',
            filename: 'extension.js',
            devtoolModuleFilenameTemplate: 'file:///[absolute-resource-path]'
        },
        optimization: {
            minimizer: [
                new TerserPlugin({
                    cache: true,
                    parallel: true,
                    sourceMap: env.production,
                    terserOptions: {
                        ecma: 8,
                        // Keep the class names otherwise @log won't provide a useful name
                        keep_classnames: true,
                        module: true
                    }
                })
            ]
        },
        externals: {
            vscode: 'commonjs vscode'
        },
        module: {
            rules: [
                {
                    test: /\.ts$/,
                    enforce: 'pre',
                    use: 'tslint-loader',
                    exclude: /node_modules/
                },
                {
                    test: /\.tsx?$/,
                    use: 'ts-loader',
                    exclude: /node_modules|\.d\.ts$/
                }
            ]
        },
        resolve: {
            extensions: ['.ts', '.tsx', '.js', '.jsx']
        },
        plugins: plugins,
        stats: {
            all: false,
            assets: true,
            builtAt: true,
            env: true,
            errors: true,
            timings: true,
            warnings: true
        }
    };
}

function getUIConfig(env) {
    const clean = ['settings.html', 'welcome.html'];
    if (env.optimizeImages) {
        console.log('Optimizing images (src/ui/images/settings/*.png)...');
        clean.push('images/settings');
    }

    const plugins = [
        // https://github.com/GoogleChromeLabs/size-plugin/issues/12
        // new SizePlugin(),
        new CleanPlugin(clean, { verbose: false }),
        new MiniCssExtractPlugin({
            filename: '[name].css'
        }),
        new HtmlPlugin({
            excludeAssets: [/.*\.main\.js/],
            excludeChunks: ['welcome'],
            template: 'settings/index.html',
            filename: path.resolve(__dirname, 'settings.html'),
            inject: true,
            inlineSource: env.production ? '.(js|css)$' : undefined,
            // inlineSource: '.(js|css)$',
            minify: env.production
                ? {
                      removeComments: true,
                      collapseWhitespace: true,
                      removeRedundantAttributes: true,
                      useShortDoctype: true,
                      removeEmptyAttributes: true,
                      removeStyleLinkTypeAttributes: true,
                      keepClosingSlash: true
                  }
                : false
        }),
        new HtmlPlugin({
            excludeAssets: [/.*\.main\.js/],
            excludeChunks: ['settings'],
            template: 'welcome/index.html',
            filename: path.resolve(__dirname, 'welcome.html'),
            inject: true,
            inlineSource: env.production ? '.(js|css)$' : undefined,
            // inlineSource: '.(js|css)$',
            minify: env.production
                ? {
                      removeComments: true,
                      collapseWhitespace: true,
                      removeRedundantAttributes: true,
                      useShortDoctype: true,
                      removeEmptyAttributes: true,
                      removeStyleLinkTypeAttributes: true,
                      keepClosingSlash: true
                  }
                : false
        }),
        new HtmlInlineSourcePlugin(),
        new ImageminPlugin({
            disable: !env.optimizeImages,
            externalImages: {
                context: path.resolve(__dirname, 'src/ui/images'),
                sources: glob.sync('src/ui/images/settings/*.png'),
                destination: path.resolve(__dirname, 'images')
            },
            cacheFolder: path.resolve(__dirname, '.cache-images'),
            gifsicle: null,
            jpegtran: null,
            optipng: null,
            pngquant: {
                quality: '85-100',
                speed: env.production ? 1 : 10
            },
            svgo: null
        })
    ];

    // if (env.production) {
    // plugins.push(new WebpackDeepScopeAnalysisPlugin());
    // }

    return {
        name: 'ui',
        context: path.resolve(__dirname, 'src/ui'),
        // This is ugly having main.scss on both bundles, but if it is added separately it will generate a js bundle :(
        entry: {
            settings: ['./settings/index.ts', './scss/main.scss'],
            welcome: ['./welcome/index.ts', './scss/main.scss']
            // main: ['./scss/main.scss']
        },
        mode: env.production ? 'production' : 'development',
        devtool: !env.production ? 'source-map' : undefined,
        output: {
            filename: '[name].js',
            path: path.resolve(__dirname, 'dist/ui'),
            publicPath: '{{root}}/dist/ui/'
        },
        optimization: {
            minimizer: [
                new TerserPlugin({
                    cache: true,
                    parallel: true,
                    sourceMap: env.production
                })
            ],
            splitChunks: {
                cacheGroups: {
                    styles: {
                        name: 'styles',
                        test: /\.css$/,
                        chunks: 'all',
                        enforce: true
                    }
                }
            }
        },
        module: {
            rules: [
                {
                    test: /\.ts$/,
                    enforce: 'pre',
                    use: [
                        {
                            loader: 'tslint-loader',
                            options: {
                                tsConfigFile: 'ui.tsconfig.json'
                            }
                        }
                    ],
                    exclude: /node_modules/
                },
                {
                    test: /\.tsx?$/,
                    use: {
                        loader: 'ts-loader',
                        options: {
                            configFile: 'ui.tsconfig.json'
                        }
                    },
                    exclude: /node_modules|\.d\.ts$/
                },
                {
                    test: /\.scss$/,
                    use: [
                        {
                            loader: MiniCssExtractPlugin.loader
                        },
                        {
                            loader: 'css-loader',
                            options: {
                                minimize: env.production,
                                sourceMap: !env.production,
                                url: false
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: !env.production
                            }
                        }
                    ],
                    exclude: /node_modules/
                }
            ]
        },
        resolve: {
            extensions: ['.ts', '.tsx', '.js', '.jsx'],
            modules: [path.resolve(__dirname, 'src/ui'), 'node_modules']
        },
        plugins: plugins,
        stats: {
            all: false,
            assets: true,
            builtAt: true,
            env: true,
            errors: true,
            timings: true,
            warnings: true
        }
    };
}
