import { __read } from "tslib";
/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-use-before-define */
import * as path from 'path';
import { evalCode } from './util';
import { init } from './core_module';
export function defineModules(allModules, opts) {
    init(opts.runtime);
    var definedModules = {};
    opts.runtime[opts.defineFuncName] = function (id, factory) {
        definedModules[id].factory = factory;
    };
    Object.entries(allModules).map(function (_a) {
        var _b = __read(_a, 2), id = _b[0], modData = _b[1];
        var mod = new Module(id, modData.url);
        definedModules[id] = mod;
        try {
            mod.defineModule(modData.code, opts.defineFuncName, opts.runtime);
        }
        catch (e) {
            opts.onError(e);
        }
    });
    Object.entries(definedModules).map(function (_a) {
        var _b = __read(_a, 2), id = _b[0], mod = _b[1];
        Object.entries(allModules[id].requires).map(function (_a) {
            var _b = __read(_a, 2), requirePath = _b[0], resolvedPath = _b[1];
            mod.dependencies[requirePath] = definedModules[resolvedPath];
        });
    });
    return definedModules;
}
// https://nodejs.org/api/modules.html#modules_the_module_object
var Module = /** @class */ (function () {
    function Module(id, url) {
        var _this = this;
        this.dependencies = {};
        this.require = function (path) {
            var dep = _this.dependencies[path];
            if (dep) {
                return dep.execute();
            }
            console.warn("Dependeny " + path + " not loaded properly for " + _this.id);
        };
        this.id = id;
        this.url = url;
    }
    Module.prototype.execute = function () {
        if (this.exports) {
            // console.warn('Using cached exports for ' + self.id)
            return this.exports;
        }
        this.exports = {};
        this.factory.call(this.exports, this.require, this.exports, this);
        return this.exports;
    };
    /**
     * Register the module
     */
    Module.prototype.defineModule = function (srcCode, defineFuncName, runtime) {
        var id = this.id;
        var ext = path.extname(id).substr(1);
        var source = srcCode;
        if (loaders[ext]) {
            source = loaders[ext](source);
        }
        var code = defineFuncName + "(\"" + id + "\", function(require, exports, module) {\n" + source + "\n})//# sourceURL=" + id;
        if (runtime.document) {
            evalCode(code, runtime.document);
        }
        else {
            console.warn('script runtime error, runtime do not has document.');
        }
        if (typeof this.factory !== 'function') {
            throw new Error("Lowcode syntax error of module " + this.url);
        }
    };
    return Module;
}());
export { Module };
var loaders = {
    json: function (src) {
        return "module.exports=" + src;
    },
    css: textLoader,
    txt: textLoader,
};
export function registerExtension(ext, transform) {
    if (loaders[ext]) {
        console.error("Duplicate transform for " + ext);
        return;
    }
    loaders[ext] = transform;
}
function textLoader(src) {
    return "module.exports=" + JSON.stringify(src);
}
//# sourceMappingURL=module.js.map