"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MiniProgramCompilerService = void 0;
const cyia_code_util_1 = require("cyia-code-util");
const path_1 = __importDefault(require("path"));
const static_injector_1 = require("static-injector");
const typescript_1 = __importDefault(require("typescript"));
const library_1 = require("../library");
const component_token_1 = require("../token/component.token");
const util_1 = require("../util");
const component_compiler_service_1 = require("./component-compiler.service");
const meta_collection_1 = require("./meta-collection");
const parse_node_1 = require("./parse-node");
const i0 = __importStar(require("static-injector"));
class MiniProgramCompilerService {
    constructor(ngTscProgram, injector, buildPlatform) {
        this.ngTscProgram = ngTscProgram;
        this.injector = injector;
        this.buildPlatform = buildPlatform;
        this.componentMap = new Map();
        this.directiveMap = new Map();
        this.resolvedDataGroup = {
            style: new Map(),
            outputContent: new Map(),
            useComponentPath: new Map(),
            otherMetaCollectionGroup: {},
        };
    }
    init() {
        this.ngCompiler = this.ngTscProgram.compiler;
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const traitCompiler = this.ngCompiler.compilation
            .traitCompiler;
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const classes = traitCompiler.classes;
        for (const [classDeclaration, classRecord] of classes) {
            const fileName = classDeclaration.getSourceFile().fileName;
            const componentTraits = classRecord.traits.filter((trait) => trait.handler.name === 'ComponentDecoratorHandler');
            if (componentTraits.length > 1) {
                throw new Error('组件装饰器异常');
            }
            componentTraits.forEach((trait) => {
                var _a, _b, _c;
                const meta = Object.assign(Object.assign({}, (_a = trait.analysis) === null || _a === void 0 ? void 0 : _a.meta), trait.resolution);
                this.resolvedDataGroup.style.set(path_1.default.normalize(fileName), 
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                (((_c = (_b = trait) === null || _b === void 0 ? void 0 : _b.analysis) === null || _c === void 0 ? void 0 : _c.styleUrls) || []).map((item) => this.resolveStyleUrl(fileName, item.url)));
                this.componentMap.set(typescript_1.default.getOriginalNode(classDeclaration), meta);
            });
            const directiveTraits = classRecord.traits.filter((trait) => trait.handler.name === 'DirectiveDecoratorHandler');
            if (directiveTraits.length > 1) {
                throw new Error('指令装饰器异常');
            }
            directiveTraits.forEach((trait) => {
                var _a;
                this.directiveMap.set(typescript_1.default.getOriginalNode(classDeclaration), 
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                (_a = trait.analysis) === null || _a === void 0 ? void 0 : _a.meta);
            });
        }
    }
    exportComponentBuildMetaMap() {
        return __awaiter(this, void 0, void 0, function* () {
            const { SelectorMatcher, CssSelector } = yield util_1.angularCompilerPromise;
            for (const [classDeclaration, meta] of this.componentMap) {
                const fileName = path_1.default.normalize(classDeclaration.getSourceFile().fileName);
                let directiveMatcher;
                if (meta.directives.length > 0) {
                    const matcher = new SelectorMatcher();
                    for (const directive of meta.directives) {
                        const selector = directive.selector;
                        const directiveClassDeclaration = typescript_1.default.getOriginalNode(
                        // eslint-disable-next-line @typescript-eslint/no-explicit-any
                        directive.ref.node);
                        const directiveMeta = this.directiveMap.get(directiveClassDeclaration);
                        const componentMeta = this.componentMap.get(directiveClassDeclaration);
                        let libraryMeta;
                        if (directive.isComponent) {
                            libraryMeta = this.getLibraryComponentMeta(
                            // eslint-disable-next-line @typescript-eslint/no-explicit-any
                            directive.ref.node);
                        }
                        if (!directive.isComponent && !directiveMeta) {
                            libraryMeta = this.getLibraryDirectiveMeta(
                            // eslint-disable-next-line @typescript-eslint/no-explicit-any
                            directive.ref.node);
                        }
                        matcher.addSelectables(CssSelector.parse(selector), {
                            directive,
                            directiveMeta,
                            componentMeta,
                            libraryMeta,
                        });
                    }
                    directiveMatcher = matcher;
                }
                const componentBuildMeta = this.buildComponentMeta(directiveMatcher, meta);
                this.resolvedDataGroup.outputContent.set(path_1.default.normalize(fileName), componentBuildMeta.content);
                this.resolvedDataGroup.useComponentPath.set(path_1.default.normalize(fileName), componentBuildMeta.useComponentPath);
                for (const key in componentBuildMeta.otherMetaGroup) {
                    if (Object.prototype.hasOwnProperty.call(componentBuildMeta.otherMetaGroup, key)) {
                        const element = componentBuildMeta.otherMetaGroup[key];
                        this.resolvedDataGroup.otherMetaCollectionGroup[key] =
                            this.resolvedDataGroup.otherMetaCollectionGroup[key] ||
                                new meta_collection_1.MetaCollection();
                        this.resolvedDataGroup.otherMetaCollectionGroup[key].merge(element);
                    }
                }
            }
            this.resolvedDataGroup.useComponentPath.forEach((value, key) => {
                value.libraryPath = Array.from(new Set(value.libraryPath));
                value.localPath = Array.from(new Set(value.localPath));
            });
            return this.resolvedDataGroup;
        });
    }
    buildComponentMeta(directiveMatcher, componentMeta) {
        const injector = static_injector_1.Injector.create({
            parent: this.injector,
            providers: [
                { provide: component_compiler_service_1.ComponentCompilerService },
                { provide: component_token_1.COMPONENT_META, useValue: componentMeta },
                {
                    provide: parse_node_1.ComponentContext,
                    useFactory: () => {
                        return new parse_node_1.ComponentContext(directiveMatcher);
                    },
                },
            ],
        });
        const instance = injector.get(component_compiler_service_1.ComponentCompilerService);
        return instance.compile();
    }
    resolveStyleUrl(componentPath, styleUrl) {
        return path_1.default.normalize(path_1.default.resolve(path_1.default.dirname(componentPath), styleUrl));
    }
    getDirectiveMap() {
        return this.directiveMap;
    }
    getComponentMap() {
        return this.componentMap;
    }
    getLibraryDirectiveMeta(classDeclaration) {
        let listeners = [];
        let properties = [];
        const directiveName = classDeclaration.name.getText();
        const selector = (0, cyia_code_util_1.createCssSelectorForTs)(classDeclaration.getSourceFile());
        const listenersNode = selector.queryOne(`VariableDeclaration[name=${directiveName}_${library_1.LIBRARY_DIRECTIVE_LISTENERS_SUFFIX}]`);
        if (listenersNode) {
            listeners = (0, util_1.literalResolve)(listenersNode.type.getText());
        }
        const propertiesNode = selector.queryOne(`VariableDeclaration[name=${directiveName}_${library_1.LIBRARY_DIRECTIVE_PROPERTIES_SUFFIX}]`);
        if (propertiesNode) {
            properties = (0, util_1.literalResolve)(propertiesNode.type.getText());
        }
        return {
            isComponent: false,
            listeners: listeners,
            properties: properties,
        };
    }
    getLibraryComponentMeta(classDeclaration) {
        const directiveName = classDeclaration.name.getText();
        const selector = (0, cyia_code_util_1.createCssSelectorForTs)(classDeclaration.getSourceFile());
        const exportPathNode = selector.queryOne(`VariableDeclaration[name=${directiveName}_${library_1.LIBRARY_COMPONENT_OUTPUT_PATH_SUFFIX}]`);
        if (!exportPathNode) {
            return undefined;
        }
        const exportPath = exportPathNode.type.getText();
        return Object.assign(Object.assign({ exportPath: (0, util_1.literalResolve)(exportPath) }, this.getLibraryDirectiveMeta(classDeclaration)), { isComponent: true });
    }
}
exports.MiniProgramCompilerService = MiniProgramCompilerService;
MiniProgramCompilerService.ɵfac = function MiniProgramCompilerService_Factory(t) { i0.ɵɵinvalidFactory(); };
MiniProgramCompilerService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MiniProgramCompilerService, factory: MiniProgramCompilerService.ɵfac });
