"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.DynamicWatchEntryPlugin = void 0;
const utils_1 = require("@angular-devkit/build-angular/src/utils");
const core_1 = require("@angular-devkit/core");
const glob = __importStar(require("glob"));
const path = __importStar(require("path"));
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const static_injector_1 = require("static-injector");
const i0 = __importStar(require("static-injector"));
function globAsync(pattern, options) {
    return new Promise((resolve, reject) => glob.default(pattern, options, (e, m) => (e ? reject(e) : resolve(m))));
}
class DynamicWatchEntryPlugin {
    constructor(options, buildPlatform) {
        this.options = options;
        this.buildPlatform = buildPlatform;
        this.entryPattern$ = new rxjs_1.BehaviorSubject(undefined);
        this.first = true;
    }
    init() {
        return __awaiter(this, void 0, void 0, function* () {
            const projectName = this.options.context.target && this.options.context.target.project;
            if (!projectName) {
                throw new Error('The builder requires a target.');
            }
            const projectMetadata = yield this.options.context.getProjectMetadata(projectName);
            this.absoluteProjectRoot = (0, core_1.normalize)((0, core_1.getSystemPath)((0, core_1.resolve)(this.options.workspaceRoot, (0, core_1.normalize)(projectMetadata.root || ''))));
            const relativeSourceRoot = projectMetadata.sourceRoot;
            const absoluteSourceRootPath = typeof relativeSourceRoot === 'string'
                ? (0, core_1.resolve)(this.options.workspaceRoot, (0, core_1.normalize)(relativeSourceRoot))
                : undefined;
            if (relativeSourceRoot) {
                this.absoluteProjectSourceRoot = (0, core_1.normalize)((0, core_1.getSystemPath)(absoluteSourceRootPath));
            }
        });
    }
    apply(compiler) {
        let rootCompilation = false;
        compiler.hooks.beforeCompile.tapPromise('DynamicWatchEntryPlugin', (compilationParams) => __awaiter(this, void 0, void 0, function* () {
            if (rootCompilation) {
                return;
            }
            this.entryPattern$.next({
                pageList: yield this.generateModuleInfo(this.options.pages || [], 'page'),
                componentList: yield this.generateModuleInfo(this.options.components || [], 'component'),
            });
        }));
        compiler.hooks.thisCompilation.tap('DynamicWatchEntryPlugin', (compilation) => {
            rootCompilation = true;
            if (this.first) {
                this.first = false;
                const patternList = (0, utils_1.normalizeAssetPatterns)([...(this.options.pages || []), ...(this.options.components || [])], this.options.workspaceRoot, this.absoluteProjectRoot, this.absoluteProjectSourceRoot);
                for (const pattern of patternList) {
                    const cwd = path.resolve(this.options.context.workspaceRoot, pattern.input);
                    compilation.fileDependencies.add(cwd);
                }
            }
        });
        // 因为监听更新的时候beforeCompile会拦截所有的,所以这么实现(因为还有一次性构建不触发watchRun,所以不能代替)
        compiler.hooks.watchRun.tap('DynamicWatchEntryPlugin', () => __awaiter(this, void 0, void 0, function* () {
            rootCompilation = false;
        }));
        // 入口移动到这里是因为ng新增了一个插件也同时修改了入口,
        compiler.hooks.environment.tap({ name: `DynamicWatchEntryPlugin`, stage: 9999 }, () => {
            const originEntryConfig = compiler.options.entry;
            compiler.options.entry = () => __awaiter(this, void 0, void 0, function* () {
                yield (0, rxjs_1.firstValueFrom)(this.entryPattern$.pipe((0, operators_1.filter)(Boolean), (0, operators_1.take)(1)));
                const entryPattern = this.entryPattern$.value;
                const list = [
                    ...entryPattern.pageList,
                    ...entryPattern.componentList,
                ];
                const result = (yield (typeof originEntryConfig === 'function'
                    ? originEntryConfig()
                    : originEntryConfig));
                if (result['app']) {
                    throw new Error('资源文件不能指定为app文件名或bundleName,请重新修改(不影响导出)');
                }
                return Object.assign(Object.assign({}, result), list.reduce((pre, cur) => {
                    pre[cur.entryName] = { import: [cur.src] };
                    return pre;
                }, {}));
            });
        });
    }
    generateModuleInfo(list, type) {
        return __awaiter(this, void 0, void 0, function* () {
            const patternList = (0, utils_1.normalizeAssetPatterns)(list, this.options.workspaceRoot, this.absoluteProjectRoot, this.absoluteProjectSourceRoot);
            const moduleList = [];
            for (const pattern of patternList) {
                const cwd = path.resolve(this.options.context.workspaceRoot, pattern.input);
                /** 当前匹配匹配到的文件 */
                const files = yield globAsync(pattern.glob, {
                    cwd,
                    dot: true,
                    nodir: true,
                    ignore: pattern.ignore || [],
                    follow: pattern.followSymlinks,
                });
                moduleList.push(...files.map((file) => {
                    const object = Object.assign(Object.assign({ entryName: path.basename(file, '.ts').replace(/\./g, '-'), fileName: file, src: path.join(cwd, file) }, pattern), { 
                        // eslint-disable-next-line @typescript-eslint/no-explicit-any
                        outputFiles: {}, 
                        // eslint-disable-next-line @typescript-eslint/no-explicit-any
                        inputFiles: {} });
                    object.inputFiles.config = object.src.replace(/\.ts$/, this.buildPlatform.fileExtname.config);
                    const outputFileName = object.fileName.replace(/\.ts$/, '').replace(/\./g, '-') + '.ts';
                    object.outputFiles.path = path
                        .join(pattern.output, outputFileName)
                        .replace(/\.ts$/, '');
                    object.outputFiles.logic =
                        object.outputFiles.path + this.buildPlatform.fileExtname.logic;
                    object.outputFiles.style =
                        object.outputFiles.path + this.buildPlatform.fileExtname.style;
                    object.outputFiles.content =
                        object.outputFiles.path + this.buildPlatform.fileExtname.content;
                    object.outputFiles.config =
                        object.outputFiles.path + this.buildPlatform.fileExtname.config;
                    object.type = type;
                    return object;
                }));
            }
            return moduleList;
        });
    }
}
DynamicWatchEntryPlugin.ɵfac = function DynamicWatchEntryPlugin_Factory(t) { i0.ɵɵinvalidFactory(); };
DynamicWatchEntryPlugin.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DynamicWatchEntryPlugin, factory: DynamicWatchEntryPlugin.ɵfac });
exports.DynamicWatchEntryPlugin = DynamicWatchEntryPlugin;
