"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebpackConfigurationChangeService = void 0;
const core_1 = require("@angular-devkit/core");
const path = __importStar(require("path"));
const operators_1 = require("rxjs/operators");
const static_injector_1 = require("static-injector");
const webpack = __importStar(require("webpack"));
const webpack_1 = require("webpack");
const webpack_bootstrap_assets_plugin_1 = require("webpack-bootstrap-assets-plugin");
const library_1 = require("../library");
const platform_1 = require("../platform/platform");
const library_template_scope_service_1 = require("./library-template-scope.service");
const dynamic_library_entry_plugin_1 = require("./plugin/dynamic-library-entry.plugin");
const dynamic_watch_entry_plugin_1 = require("./plugin/dynamic-watch-entry.plugin");
const export_mini_program_assets_plugin_1 = require("./plugin/export-mini-program-assets.plugin");
const token_1 = require("./token");
const i0 = __importStar(require("static-injector"));
class WebpackConfigurationChangeService {
    constructor(options, context, config, injector) {
        this.options = options;
        this.context = context;
        this.config = config;
        this.injector = injector;
    }
    init() {
        this.injector = static_injector_1.Injector.create({
            parent: this.injector,
            providers: [
                { provide: export_mini_program_assets_plugin_1.ExportMiniProgramAssetsPlugin },
                { provide: library_template_scope_service_1.LibraryTemplateScopeService },
                {
                    provide: token_1.TS_CONFIG_TOKEN,
                    useValue: path.resolve(this.context.workspaceRoot, this.options.tsConfig),
                },
                {
                    provide: dynamic_watch_entry_plugin_1.DynamicWatchEntryPlugin,
                    deps: [platform_1.BuildPlatform],
                    useFactory: (buildPlatform) => {
                        return new dynamic_watch_entry_plugin_1.DynamicWatchEntryPlugin({
                            pages: this.options.pages,
                            components: this.options.components,
                            workspaceRoot: (0, core_1.normalize)(this.context.workspaceRoot),
                            context: this.context,
                            config: this.config,
                        }, buildPlatform);
                    },
                },
                { provide: dynamic_library_entry_plugin_1.DynamicLibraryComponentEntryPlugin },
            ],
        });
        this.buildPlatform = this.injector.get(platform_1.BuildPlatform);
        this.buildPlatform.fileExtname.config =
            this.buildPlatform.fileExtname.config || '.json';
        this.config.output.globalObject = this.buildPlatform.globalObject;
    }
    change() {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            this.buildPlatformCompatible();
            this.exportAssets();
            yield this.pageHandle();
            this.addLoader();
            this.globalVariableChange();
            this.changeStylesExportSuffix();
            (_a = this.config.plugins) === null || _a === void 0 ? void 0 : _a.push(this.injector.get(dynamic_library_entry_plugin_1.DynamicLibraryComponentEntryPlugin));
            (_b = this.config.plugins) === null || _b === void 0 ? void 0 : _b.push(new webpack.NormalModuleReplacementPlugin(/^angular-miniprogram\/platform\/wx$/, `angular-miniprogram/platform/${this.buildPlatform.packageName}`));
        });
    }
    buildPlatformCompatible() {
        var _a, _b, _c, _d;
        if (this.buildPlatform.packageName == 'zfb') {
            (_b = (_a = this.config.resolve) === null || _a === void 0 ? void 0 : _a.conditionNames) === null || _b === void 0 ? void 0 : _b.shift();
            (_d = (_c = this.config.resolve) === null || _c === void 0 ? void 0 : _c.mainFields) === null || _d === void 0 ? void 0 : _d.shift();
        }
    }
    pageHandle() {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const dynamicWatchEntryInstance = this.injector.get(dynamic_watch_entry_plugin_1.DynamicWatchEntryPlugin);
            yield dynamicWatchEntryInstance.init();
            dynamicWatchEntryInstance.entryPattern$
                .pipe((0, operators_1.filter)((item) => !!item))
                .subscribe((result) => {
                this.entryList = [...result.pageList, ...result.componentList];
                this.exportMiniProgramAssetsPluginInstance.setEntry(result.pageList, result.componentList);
            });
            (_a = this.config.plugins) === null || _a === void 0 ? void 0 : _a.push(dynamicWatchEntryInstance);
            // 出口
            const oldFileName = this.config.output.filename;
            this.config.output.filename = (chunkData) => {
                const page = this.entryList.find((item) => item.entryName === chunkData.chunk.name);
                if (page) {
                    return page.outputFiles.logic;
                }
                return oldFileName;
            };
            // 共享依赖
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            const oldChunks = this.config.optimization.splitChunks.cacheGroups
                .defaultVendors.chunks;
            this.config.optimization
                .splitChunks.cacheGroups.defaultVendors.chunks = (chunk) => {
                if (this.entryList.find((item) => item.entryName === chunk.name) ||
                    chunk.name.startsWith(`${library_1.LIBRARY_OUTPUT_ROOTDIR}/`)) {
                    return true;
                }
                return oldChunks(chunk);
            };
            this.config.optimization.splitChunks
                .cacheGroups['moduleChunks'] = {
                test: (module) => {
                    const name = module.nameForCondition();
                    return ((name &&
                        name.endsWith('.ts') &&
                        !/[\\/]node_modules[\\/]/.test(name)) ||
                        (name === null || name === void 0 ? void 0 : name.includes('angular-miniprogram\\dist')));
                },
                minChunks: 2,
                minSize: 0,
                name: 'module-chunk',
                chunks: 'all',
            };
            // 出口保留必要加载
            const assetsPlugin = new webpack_bootstrap_assets_plugin_1.BootstrapAssetsPlugin();
            assetsPlugin.hooks.removeChunk.tap('pageHandle', (chunk) => {
                if (this.entryList.some((page) => page.entryName === chunk.name) ||
                    [...chunk.files].some((file) => file.endsWith(this.buildPlatform.fileExtname.style)) ||
                    chunk.name.startsWith(`${library_1.LIBRARY_OUTPUT_ROOTDIR}/`)) {
                    return true;
                }
                return false;
            });
            assetsPlugin.hooks.emitAssets.tap('pageHandle', (object, json) => {
                return {
                    'app.js': this.buildPlatform.importTemplate +
                        json.scripts.map((item) => `require('./${item.src}')`).join(';'),
                };
            });
            this.config.plugins.push(assetsPlugin);
        });
    }
    exportAssets() {
        this.exportMiniProgramAssetsPluginInstance = this.injector.get(export_mini_program_assets_plugin_1.ExportMiniProgramAssetsPlugin);
        this.config.plugins.unshift(this.exportMiniProgramAssetsPluginInstance);
    }
    addLoader() {
        var _a, _b, _c, _d;
        this.config.module.rules.unshift({
            test: /\.ts$/,
            loader: require.resolve(path.join(__dirname, './loader/component-template.loader')),
        });
        (_b = (_a = this.config.module) === null || _a === void 0 ? void 0 : _a.rules) === null || _b === void 0 ? void 0 : _b.unshift({
            test: /\.mjs$/,
            loader: require.resolve(path.join(__dirname, './loader/library.loader')),
        });
        (_d = (_c = this.config.module) === null || _c === void 0 ? void 0 : _c.rules) === null || _d === void 0 ? void 0 : _d.unshift({
            test: /\.mjs$/,
            loader: require.resolve(path.join(__dirname, './loader/library-template.loader')),
        });
    }
    globalVariableChange() {
        const defineObject = {
            global: `${this.buildPlatform.globalObject}.__global`,
            window: `${this.buildPlatform.globalVariablePrefix}`,
            globalThis: `${this.buildPlatform.globalVariablePrefix}`,
            Zone: `${this.buildPlatform.globalVariablePrefix}.Zone`,
            setTimeout: `${this.buildPlatform.globalVariablePrefix}.setTimeout`,
            clearTimeout: `${this.buildPlatform.globalVariablePrefix}.clearTimeout`,
            setInterval: `${this.buildPlatform.globalVariablePrefix}.setInterval`,
            clearInterval: `${this.buildPlatform.globalVariablePrefix}.clearInterval`,
            Promise: `${this.buildPlatform.globalVariablePrefix}.Promise`,
            Reflect: `${this.buildPlatform.globalVariablePrefix}.Reflect`,
            requestAnimationFrame: `${this.buildPlatform.globalVariablePrefix}.requestAnimationFrame`,
            cancelAnimationFrame: `${this.buildPlatform.globalVariablePrefix}.cancelAnimationFrame`,
            performance: `${this.buildPlatform.globalVariablePrefix}.performance`,
            navigator: `${this.buildPlatform.globalVariablePrefix}.navigator`,
            wx: this.buildPlatform.globalObject,
            miniProgramPlatform: `"${this.buildPlatform.globalObject}"`,
        };
        if (this.config.mode === 'development') {
            defineObject['ngDevMode'] = `${this.buildPlatform.globalObject}.__global.ngDevMode`;
        }
        this.config.plugins.push(new webpack_1.DefinePlugin(defineObject));
    }
    changeStylesExportSuffix() {
        var _a;
        const index = this.config.plugins.findIndex((plugin) => Object.getPrototypeOf(plugin).constructor.name ===
            'MiniCssExtractPlugin');
        if (index > -1) {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            const pluginInstance = this.config.plugins[index];
            const pluginPrototype = Object.getPrototypeOf(pluginInstance);
            (_a = this.config.plugins) === null || _a === void 0 ? void 0 : _a.splice(index, 1, new pluginPrototype.constructor({
                filename: 'app' + this.buildPlatform.fileExtname.style,
            }));
        }
        else {
            throw new Error('没有找到MiniCssExtractPlugin插件,无法修改生成style');
        }
    }
}
WebpackConfigurationChangeService.ɵfac = function WebpackConfigurationChangeService_Factory(t) { i0.ɵɵinvalidFactory(); };
WebpackConfigurationChangeService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: WebpackConfigurationChangeService, factory: WebpackConfigurationChangeService.ɵfac });
exports.WebpackConfigurationChangeService = WebpackConfigurationChangeService;
