"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.codegen = void 0;
const tslib_1 = require("tslib");
const path_1 = tslib_1.__importDefault(require("path"));
const fs_1 = tslib_1.__importDefault(require("fs"));
const core_1 = require("@il2js/core");
const Targets_1 = require("./Targets");
const TypeRegistry_1 = require("./TypeRegistry");
const OptimizeTypes_1 = require("./OptimizeTypes");
const GameAssembly_1 = require("./GameAssembly");
const TypeVisitorExecutor_1 = require("./TypeVisitorExecutor");
const defaultCodegenApi = {
    writeFile(filePath, data) {
        return fs_1.default.promises.writeFile(filePath, data, 'utf8');
    },
};
async function codegen(config, { api, progressCallback } = {}) {
    const { gameAssembly, output, targets, types, force, optimize, filter, visitors } = config;
    const gasm = GameAssembly_1.isGameAssembly(gameAssembly)
        ? gameAssembly
        : new GameAssembly_1.GameAssembly(gameAssembly.dll, gameAssembly.metadata, gameAssembly.version, filter);
    const outputFile = path_1.default.join(output.outputDir, output.entry);
    if (gasm.cached && fs_1.default.existsSync(outputFile) && !force) {
        console.log(`Re-using entry ${outputFile}`);
        return;
    }
    await gasm.load();
    if (visitors) {
        visitors.forEach((visitor) => {
            gasm.structs.TypeInfoList = TypeVisitorExecutor_1.executeVisitor(visitor, gasm.structs.TypeInfoList);
            gasm.structs.TypeNameToStaticMethods = TypeVisitorExecutor_1.executeMethodVisitor(visitor, gasm.structs.TypeNameToStaticMethods);
        });
    }
    if (optimize) {
        OptimizeTypes_1.optimizeTypes(gasm.structs);
    }
    const typeRegistry = new TypeRegistry_1.TypeRegistry(types);
    for (const currentTarget of Object.values(targets)) {
        let targetName;
        let targetConfig = config;
        if (typeof currentTarget !== 'string') {
            targetName = currentTarget[0];
            if (currentTarget[1]) {
                targetConfig = { ...config, ...currentTarget[1] };
            }
        }
        else {
            targetName = currentTarget;
        }
        const Target = Object.values(Targets_1.Targets).find((target) => target.targetName === targetName);
        core_1.assert(Target, RangeError);
        const targetInstance = new Target(path_1.default.basename(gasm.gameAssemblyDllPath), gasm.version, typeRegistry, api !== null && api !== void 0 ? api : defaultCodegenApi);
        // eslint-disable-next-line no-await-in-loop
        await targetInstance.process(gasm.structs, targetConfig, progressCallback);
        // eslint-disable-next-line no-await-in-loop
        await targetInstance.write(output);
    }
}
exports.codegen = codegen;
//# sourceMappingURL=Codegen.js.map