"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const tools_1 = __importDefault(require("./tools"));
class Formatter {
    constructor(data) {
        this.data = data;
        this.replacerMap = {};
    }
    exec() {
        const { data } = this;
        this.formated = Object.assign(Object.assign({}, data), { actions: this.formatActions(data.actions), plugins: this.formatPlugins(data.plugins), components: this.formatComponents(data.components), pluginInstances: this.formatPluginInstances(data.pluginInstances), componentInstances: this.formatComponentInstances(data.componentInstances), meta: this.formatMetaData(data.meta) });
        return this;
    }
    replace(value) {
        let result = typeof value === 'object' ? Formatter.stringifyObject(value) : value;
        Object.entries(this.replacerMap).forEach(([k, v]) => {
            result = result.replace(new RegExp(`"${k}"`, 'g'), v);
        });
        return result;
    }
    static formatInjectedStyle(styles) {
        return styles.filter(i => !!i).join('\n');
    }
    static stringifyObject(v) {
        return JSON.stringify(v, null, 4);
    }
    static formatGlobalStyle(style) {
        const result = Object.entries(tools_1.default.mergeCommonStyle(style))
            .reduce((styles, [propName, propValue]) => {
            styles.push(`${propName}: ${propValue} !important;`);
            return styles;
        }, [])
            .join('\n');
        return `body {\n\t${result}\n}`;
    }
    stringify() {
        const v = this.formated;
        return {
            componentImports: v.componentImports.join(';\n'),
            components: this.replace(v.components),
            componentInstances: this.replace(v.componentInstances),
            pluginImports: v.pluginImports.join(';\n'),
            plugins: this.replace(v.plugins),
            pluginInstances: this.replace(v.pluginInstances),
            actionImports: v.actionImports.join(';\n'),
            actions: this.replace(v.actions),
            globalStyle: Formatter.formatGlobalStyle(v.globalStyle),
            meta: this.replace(v.meta),
            global: Formatter.stringifyObject(v.global),
            jimuVars: Formatter.stringifyObject(v.jimuVars),
            injectedStyle: Formatter.formatInjectedStyle(v.injectedStyle),
        };
    }
    formatComponents(components) {
        return Object.entries(components).reduce((accu, [id, component]) => {
            accu[id] = Object.assign({ component: `__impage_render_template_component-${id}__` }, component);
            this.replacerMap[accu[id].component] = component.name;
            return accu;
        }, {});
    }
    formatActions(actions) {
        return Object.entries(actions).reduce((accu, [id, action]) => {
            accu[id] = Object.assign({ action: `__impage_render_template_action-${id}__` }, action);
            this.replacerMap[accu[id].action] = action.name;
            return accu;
        }, {});
    }
    formatPlugins(plugins) {
        return Object.entries(plugins).reduce((accu, [id, plugin]) => {
            accu[id] = Object.assign({ plugin: `__impage_render_template_plugin-${id}__` }, plugin);
            this.replacerMap[accu[id].plugin] = plugin.name;
            return accu;
        }, {});
    }
    formatComponentInstances(componentInstances) {
        return componentInstances.map(i => {
            const instance = Object.assign({}, i);
            const id = instance.component;
            const component = this.data.components[id];
            if (instance.children && instance.children.length) {
                instance.children = this.formatComponentInstances(instance.children);
            }
            if (instance.actions && instance.actions.length) {
                instance.actions = this.formatActionInstances(instance.actions);
            }
            if (component.__implementHotArea && instance.data.hotAreas && instance.data.hotAreas.length) {
                instance.data.hotAreas = this.formatHotAreas(instance.data.hotAreas);
            }
            instance.component = `__impage_render_template_component-instance-${id}__`;
            this.replacerMap[instance.component] = `components['${id}']`;
            return instance;
        });
    }
    formatActionInstances(actionInstance) {
        return actionInstance.map(i => {
            const id = i.action;
            const instance = Object.assign(Object.assign({}, i), { action: `__impage_render_template_action-instance-${id}__` });
            this.replacerMap[instance.action] = `actions['${id}']`;
            return instance;
        });
    }
    formatHotAreas(hotAreas) {
        return hotAreas.map(i => {
            return Object.assign(Object.assign({}, i), { actions: this.formatActionInstances(i.actions) });
        });
    }
    formatPluginInstances(pluginInstance) {
        return pluginInstance.map(i => {
            const id = i.plugin;
            const instance = Object.assign(Object.assign({}, i), { plugin: `__impage_render_template_plugin-instance-${id}__` });
            this.replacerMap[instance.plugin] = `plugins['${id}']`;
            return instance;
        });
    }
    formatMetaData(meta) {
        const result = Object.assign(Object.assign({}, meta), { start: '__impage_render_template_meta_start__', end: '__impage_render_template_meta_end__' });
        const { start, end } = meta;
        this.replacerMap[result.start] = `new Date('${start}')`;
        this.replacerMap[result.end] = `new Date('${end}')`;
        return result;
    }
}
const formatTemplateData = function (data) {
    const formatter = new Formatter(data);
    return formatter.exec().stringify();
};
function pxWithAuto(px) {
    return px === 'auto' ? 'auto' : `${px}px`;
}
function percent(p) {
    return `${p}%`;
}
const MAX_MEMO_ITEMS = 20;
function withMemo(fn) {
    Object.defineProperty(fn, '__memo', {
        get() {
            return [];
        },
    });
    return function (arg) {
        const memo = fn.__memo;
        if (memo) {
            const item = memo.find(i => i.arg === arg);
            if (item) {
                return item.result;
            }
        }
        const result = fn(arg);
        memo.push({ arg, result });
        setTimeout(() => {
            if (memo.length > MAX_MEMO_ITEMS) {
                memo.splice(0, memo.length - MAX_MEMO_ITEMS);
            }
        }, 10);
        return result;
    };
}
function iGetInjectSchema(schema) {
    return Object.entries(schema).reduce((maps, [key, { inject }]) => {
        if (!inject) {
            return maps;
        }
        const items = Array.isArray(inject) ? inject : [inject];
        items.forEach(({ attr, selector, format }) => {
            const iAttr = Array.isArray(attr) ? attr : [attr || key];
            const iSelector = Array.isArray(selector) ? selector.join(', ') : selector;
            let iFormat = typeof format === 'function' ? format : i => i.toString();
            if (format === 'px') {
                iFormat = pxWithAuto();
            }
            else if (format === 'percent') {
                iFormat = percent;
            }
            maps.push({ key, attr: iAttr, selector: iSelector, format: iFormat });
        });
        return maps;
    }, []);
}
const getInjectSchema = withMemo(iGetInjectSchema);
const formatInjectStyles = function (scope, style, schema) {
    return getInjectSchema(schema)
        .reduce((accu, { key, attr, selector, format }) => {
        const v = style[key];
        if (!v) {
            return accu;
        }
        const value = format(v);
        accu.push(`\t#${scope} ${selector} { ${attr.map(i => `${i}: ${value}`).join('; ')} }`);
        return accu;
    }, [])
        .join('\n');
};
exports.default = {
    formatTemplateData,
    formatInjectStyles
};
//# sourceMappingURL=utils.js.map