"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WxContainer = void 0;
const mini_program_compiler_1 = require("../../../mini-program-compiler");
const type_predicate_1 = require("../../util/type-predicate");
class WxContainer {
    constructor(parent) {
        this.parent = parent;
        this.templateStr = '';
        this.childContainerList = [];
        this.metaCollection = new mini_program_compiler_1.MetaCollection();
    }
    _compileTemplate(node) {
        if ((0, type_predicate_1.isNgElementMeta)(node)) {
            return this.ngElementTransform(node);
        }
        else if ((0, type_predicate_1.isNgBoundTextMeta)(node)) {
            return this.ngBoundTextTransform(node);
        }
        else if ((0, type_predicate_1.isNgTextMeta)(node)) {
            return this.ngTextTransform(node);
        }
        else if ((0, type_predicate_1.isNgContentMeta)(node)) {
            return this.ngContentTransform(node);
        }
        else if ((0, type_predicate_1.isNgTemplateMeta)(node)) {
            return this.ngTemplateTransform(node);
        }
        else {
            throw new Error('未知的ng节点元数据');
        }
    }
    compileNode(node) {
        this.templateStr += this._compileTemplate(node);
    }
    ngElementTransform(node) {
        var _a;
        if (node.componentMeta) {
            if (node.componentMeta.exportPath) {
                this.metaCollection.libraryPath.add({
                    selector: node.componentMeta.selector,
                    path: node.componentMeta.exportPath,
                    className: node.componentMeta.className,
                });
            }
            else {
                this.metaCollection.localPath.add({
                    path: node.componentMeta.filePath,
                    selector: node.componentMeta.selector,
                    className: node.componentMeta.className,
                });
            }
        }
        const children = node.children.map((child) => this._compileTemplate(child));
        const commonTagProperty = `${this.setComponentIdentification((_a = node.componentMeta) === null || _a === void 0 ? void 0 : _a.isComponent, node.index)} ${this.elementPropertyAndEvent(node, node.index).join(' ')}`;
        if (node.singleClosedTag) {
            return `<${node.tagName} ${commonTagProperty}/>`;
        }
        return `<${node.tagName} ${node.tagName === 'block' ? '' : commonTagProperty}>${children.join('')}</${node.tagName}>`;
    }
    ngBoundTextTransform(node) {
        return `{{nodeList[${node.index}].value}}`;
    }
    ngContentTransform(node) {
        return node.name ? `<slot name="${node.name}"></slot>` : `<slot></slot>`;
    }
    ngTemplateTransform(node) {
        let content = '';
        const defineTemplateName = node.defineTemplateName;
        const childContainer = new WxContainer(this);
        const globalTemplate = this.isGlobalTemplate(node.defineTemplateName);
        if (globalTemplate) {
            if (this.fromTemplate && this.fromTemplate !== globalTemplate) {
                throw new Error(`全局ng-template中不可包含其他位置的ng-template,当前为${this.fromTemplate},包含${globalTemplate}`);
            }
            else if (globalTemplate) {
                childContainer.fromTemplate = globalTemplate;
                childContainer.defineTemplateName = defineTemplateName;
            }
        }
        else {
            childContainer.fromTemplate = this.fromTemplate;
            childContainer.defineTemplateName = defineTemplateName;
        }
        this.childContainerList.push(childContainer);
        node.children.forEach((childNode) => {
            childContainer.compileNode(childNode);
        });
        if (this.fromTemplate === childContainer.fromTemplate) {
            this.metaCollection.templateList.push({
                name: defineTemplateName,
                content: `<template name="${defineTemplateName}">${childContainer.templateStr}</template>`,
            });
        }
        content += `<block ${WxContainer.globalConfig.directivePrefix}${WxContainer.globalConfig.seq}for="{{nodeList[${node.index}]}}" ${WxContainer.globalConfig.directivePrefix}${WxContainer.globalConfig.seq}key="index">
      <template is="{{item.__templateName||'${defineTemplateName}'}}" ${this.getTemplateDataStr(node.index, `index`)}></template>
      </block>`;
        return content;
    }
    ngTextTransform(node) {
        return `${node.value}`;
    }
    getTemplateDataStr(directiveIndex, indexName) {
        return `data="${WxContainer.globalConfig.templateInterpolation[0]}...nodeList[${directiveIndex}][${indexName}] ${WxContainer.globalConfig.templateInterpolation[1]}"`;
    }
    export() {
        return {
            wxmlTemplate: this.templateStr,
        };
    }
    setComponentIdentification(isComponent, nodeIndex) {
        if (isComponent) {
            return `nodePath="{{nodePath}}" nodeIndex="${nodeIndex}"`;
        }
        return ``;
    }
    elementPropertyAndEvent(node, index) {
        var _a, _b, _c, _d;
        const propertyMap = new Map();
        const attributeMap = new Map();
        propertyMap.set('class', `nodeList[${index}].class`);
        propertyMap.set('style', `nodeList[${index}].style`);
        Object.entries(node.attributes)
            .filter(([key, value]) => value !== '')
            .forEach(([key, value]) => {
            attributeMap.set(key, value);
        });
        node.inputs
            .filter((property) => {
            var _a, _b, _c, _d, _e, _f, _g, _h;
            return !((((_b = (_a = node.componentMeta) === null || _a === void 0 ? void 0 : _a.inputs) === null || _b === void 0 ? void 0 : _b.includes(property)) ||
                ((_d = (_c = node.directiveMeta) === null || _c === void 0 ? void 0 : _c.inputs) === null || _d === void 0 ? void 0 : _d.includes(property))) &&
                !(((_f = (_e = node.directiveMeta) === null || _e === void 0 ? void 0 : _e.properties) === null || _f === void 0 ? void 0 : _f.includes(property)) ||
                    ((_h = (_g = node.componentMeta) === null || _g === void 0 ? void 0 : _g.properties) === null || _h === void 0 ? void 0 : _h.includes(property))));
        })
            .filter((key) => !/^(class\.?|style\.?)/.test(key))
            .forEach((key) => {
            propertyMap.set(key, `nodeList[${index}].property.${key}`);
        });
        [
            ...(((_a = node.directiveMeta) === null || _a === void 0 ? void 0 : _a.properties) || []),
            ...(((_b = node.componentMeta) === null || _b === void 0 ? void 0 : _b.properties) || []),
        ]
            .filter((key) => !/^(class\.?|style\.?)/.test(key))
            .forEach((key) => {
            propertyMap.set(key, `nodeList[${index}].property.${key}`);
        });
        const eventList = [
            ...node.outputs.filter((item) => {
                var _a, _b;
                return !(((_a = node.componentMeta) === null || _a === void 0 ? void 0 : _a.outputs.some((output) => output === item)) ||
                    ((_b = node.directiveMeta) === null || _b === void 0 ? void 0 : _b.outputs.some((output) => output === item)));
            }),
            ...(((_c = node.directiveMeta) === null || _c === void 0 ? void 0 : _c.listeners) || []),
            ...(((_d = node.componentMeta) === null || _d === void 0 ? void 0 : _d.isComponent) ? node.componentMeta.listeners : []),
        ];
        const result = WxContainer.globalConfig.eventListConvert(eventList);
        if (result) {
            propertyMap.set(`data-node-path`, `nodePath`);
            propertyMap.set(`data-node-index`, `${index}`);
        }
        return [
            ...Array.from(attributeMap.entries()).map(([key, value]) => `${key}="${value}"`),
            ...Array.from(propertyMap.entries()).map(([key, value]) => `${key}="{{${value}}}"`),
            result,
        ];
    }
    static initWxContainerFactory(globalConfig) {
        this.globalConfig = globalConfig;
    }
    isGlobalTemplate(name) {
        const result = name.match(/^\$\$mp\$\$([^$]+)\$\$(.*)/);
        if (!result) {
            return undefined;
        }
        return result[1];
    }
    exportMetaCollectionGroup() {
        const obj = {};
        if (!this.fromTemplate) {
            obj.$inline = obj.$inline || new mini_program_compiler_1.MetaCollection();
            obj.$inline.merge(this.metaCollection);
        }
        else if (this.fromTemplate == '__self__') {
            obj.$self = obj.$self || new mini_program_compiler_1.MetaCollection();
            obj.$self.merge(this.metaCollection);
            obj.$self.templateList.push({
                name: this.defineTemplateName,
                content: `<template name="${this.defineTemplateName}">${this.templateStr}</template>`,
            });
        }
        else {
            obj[this.fromTemplate] = obj[this.fromTemplate] || new mini_program_compiler_1.MetaCollection();
            obj[this.fromTemplate].merge(this.metaCollection);
            obj[this.fromTemplate].templateList.push({
                name: this.defineTemplateName,
                content: `<template name="${this.defineTemplateName}">${this.templateStr}</template>`,
            });
        }
        this.childContainerList.forEach((container) => {
            const result = container.exportMetaCollectionGroup();
            for (const key in result) {
                if (Object.prototype.hasOwnProperty.call(result, key)) {
                    const element = result[key];
                    obj[key] = obj[key] || new mini_program_compiler_1.MetaCollection();
                    obj[key].merge(element);
                }
            }
        });
        return obj;
    }
}
exports.WxContainer = WxContainer;
