/*
 * worker-plugin
 */

const path = require('path');
const webpack = require('webpack');
const { WorkerPluginName } = require('./constants');
const ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers');

class FuiWorkerPlugin {
    constructor(options = {}) {
        this.options = options;
    }

    apply(compiler) {
        // 为主线程构建添加 __WORKER__ 环境变量, 构建中区分不同线程源码, 实现代码拆减
        compiler.hooks.afterPlugins.tap(WorkerPluginName, compiler => {
            new webpack.DefinePlugin({
                // __WORKER__ 表示当前所在线程是否是 worker 线程
                // 主线程构建中为 false
                __WORKER__: false,
            }).apply(compiler);
        });

        // 添加自定义的worker entry-loader
        compiler.hooks.afterResolvers.tap(WorkerPluginName, compiler => {
            /**
             * https://webpack.js.org/configuration/resolve/#resolveloader
             * 使用 resolveloader 添加自定义的 worker loader
             */
            if (!compiler.options.resolveLoader) {
                compiler.options.resolveLoader = {
                    alias: {},
                };
            }
            if (!compiler.options.resolveLoader.alias) {
                compiler.options.resolveLoader.alias = {};
            }

            // 动态添加 worker 的 worker-loader, 命名为 "fui-worker"
            compiler.options.resolveLoader.alias['fui-worker'] = path.resolve(__dirname, './worker-loader.js');
        });

        // 将FuiWorkerPlugin的参数传递给fui-worker loader
        compiler.hooks.compilation.tap(WorkerPluginName, compilation => {
            compilation.hooks.normalModuleLoader.tap(WorkerPluginName, (context, module) => {
                // 仅提供给fui-worker
                const fuiLoader = module.loaders.find(loader => loader.loader.indexOf('fui-worker') !== -1);

                if (fuiLoader) {
                    const resource = module.resource;

                    if (!resource) return;

                    // fui-worker通过options读取
                    context.options = context.options || {};

                    const index = resource.indexOf('?');
                    
                    if (ModuleFilenameHelpers.matchObject(
                            this.options,
                            index < 0 ? resource : resource.substr(0, index)
                        )) {
                        for (const key of Object.keys(this.options)) {
                            // 忽略关键属性
                            if (key === "include" || key === "exclude" || key === "test") {
                                continue;
                            }
                            
                            context.options[key] = this.options[key];
                        }
                    }
                }
            })
        })
    }
}

module.exports = FuiWorkerPlugin;