import { __awaiter } from "tslib";
import { ECodeType } from '@cloudbase/cals';
import { evalCodeCodules } from './parser/base';
import { StateParser, ComputedParser, LifeCycleParser, HandlerParser, NormalModuleParser, RendererParser, } from './parser/index';
export { generateStyleModuleMap } from './parser/lessParser';
const moduleParsers = {
    [ECodeType.LIFECYCLE]: new LifeCycleParser(),
    [ECodeType.COMPUTEDN]: new ComputedParser(),
    [ECodeType.STATE]: new StateParser(),
    [ECodeType.NORMAL_MODULE]: new NormalModuleParser(),
    [ECodeType.HANDLER_FN]: new HandlerParser(),
    [ECodeType.RENDERER]: new RendererParser(),
};
// 用于页面内通信
let lastError = [];
function addError(e, file) {
    const err = { file, message: e.message || e.stack };
    lastError.push(err);
}
export const lowcodeContext = {};
// export const widgetsContext = {} as WidgetsContext;
// Just for debug
// Object.defineProperty(window, '__widgetsContext', {
//   get: () => widgetsContext,
// });
Object.defineProperty(window, '__lowcodeContext', {
    get: () => lowcodeContext,
    set: (value) => {
        console.warn('__lowcodeContext can not been set to another value');
    },
});
function quickClone(json) {
    return JSON.parse(JSON.stringify(json));
}
/**
 * Reexecute all low code when updated
 */
export function generateLowcodeModules({ runtimeWindow, codeModulesMap = {}, onDependencyMiss = () => { }, dependencies = {}, externals = {}, }) {
    return __awaiter(this, void 0, void 0, function* () {
        const allModules = {
            global: quickClone(filterCssCodeModules(codeModulesMap.global)),
        };
        for (let pageId in codeModulesMap) {
            let modules = pageId === 'global'
                ? codeModulesMap[pageId]
                : codeModulesMap[pageId].map((module) => {
                    var _a, _b;
                    return Object.assign(Object.assign({}, module), { path: (_b = (_a = module.path) === null || _a === void 0 ? void 0 : _a.replace) === null || _b === void 0 ? void 0 : _b.call(_a, /^.*?\//, `${pageId}/`) });
                });
            allModules[pageId] = quickClone(filterCssCodeModules(modules));
        }
        const result = yield applyLowcode(allModules, {
            dependencies,
            onDependencyMiss,
            runtimeWindow,
            externals,
        });
        Object.assign(lowcodeContext, result);
        return lowcodeContext;
    });
}
export function applyLowcode(allModules, opts) {
    var _a;
    return __awaiter(this, void 0, void 0, function* () {
        const innerEvalContext = {};
        for (const type in moduleParsers) {
            // eslint-disable-line
            moduleParsers[type].onStart(innerEvalContext);
        }
        (_a = opts.onBeforeParse) === null || _a === void 0 ? void 0 : _a.call(opts, innerEvalContext);
        lastError = [];
        // @ts-ignore
        opts.onCodeError = addError;
        const evaledModules = yield evalCodeCodules(allModules, opts);
        // eslint-disable-next-line no-restricted-syntax
        for (const pageId in evaledModules) {
            // eslint-disable-line
            evaledModules[pageId].forEach((m) => {
                const parser = moduleParsers[m.codeType];
                if (!parser) {
                    if (m.codeType !== 'mp_config') {
                        console.error(`Can not handle code module of type ${m.codeType}`);
                    }
                    return;
                }
                try {
                    parser.parseModule(pageId, m);
                }
                catch (e) {
                    console.error('Error parse module', m, e);
                }
            });
        }
        // eslint-disable-next-line no-restricted-syntax
        for (const type in moduleParsers) {
            try {
                moduleParsers[type].onEnd(innerEvalContext);
            }
            catch (e) {
                console.error('Module parser error', e);
            }
        }
        return innerEvalContext;
    });
}
// 去掉css 代码
function filterCssCodeModules(modules = []) {
    return modules.filter((module) => module.codeType !== ECodeType.STYLE && module.codeType !== ECodeType.THEME);
}
// export function cleanWidgetsContext() {
//   for (let key in widgetsContext) {
//     delete widgetsContext[key];
//   }
// }
export function cleanLowcodeContext() {
    // @ts-ignore For debugging
    Object.keys(lowcodeContext).forEach((key) => {
        delete lowcodeContext[key];
    });
}
