"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.optimizeTypes = exports.isSame = exports.isEmpty = void 0;
/* eslint-disable no-cond-assign */
/* eslint-disable @typescript-eslint/no-loop-func */
const core_1 = require("@il2js/core");
const TypeVisitorExecutor_1 = require("./TypeVisitorExecutor");
function isEmpty(type) {
    var _a, _b, _c;
    return !((_a = type.Fields) === null || _a === void 0 ? void 0 : _a.length) && !((_b = type.StaticFields) === null || _b === void 0 ? void 0 : _b.length) && !((_c = type.NestedTypes) === null || _c === void 0 ? void 0 : _c.length);
}
exports.isEmpty = isEmpty;
function isSame(a, b) {
    return a.Namespace === b.Namespace && a.TypeName === b.TypeName;
}
exports.isSame = isSame;
function typeName(type) {
    return core_1.excludeUndefined([type.Namespace, type.TypeName]).join('.');
}
function optimizeWorker(file) {
    let hasOptimized = false;
    let types = file.TypeInfoList;
    for (const type of file.TypeInfoList) {
        if (isEmpty(type)) {
            // collapse to base type?
            if (type.Type.BaseType) {
                console.info(`Collapsing empty '${typeName(type.Type)}' to base type '${typeName(type.Type.BaseType)}'`);
                types = TypeVisitorExecutor_1.executeVisitor({
                    visitTypeDef(typeDef) {
                        if (isSame(type.Type, typeDef.Type)) {
                            hasOptimized = true;
                            return undefined;
                        }
                        return typeDef;
                    },
                    visitTypeUsage(typeUsage) {
                        if (isSame(type.Type, typeUsage)) {
                            hasOptimized = true;
                            return type.Type.BaseType;
                        }
                        return typeUsage;
                    },
                }, types);
            }
            else {
                console.info(`Removing empty '${core_1.excludeUndefined([type.Type.Namespace, type.Type.TypeName]).join('.')}' type`);
                types = TypeVisitorExecutor_1.executeVisitor({
                    visitTypeDef(typeDef) {
                        if (isSame(type.Type, typeDef.Type)) {
                            hasOptimized = true;
                            return undefined;
                        }
                        return typeDef;
                    },
                }, types);
            }
        }
    }
    // eslint-disable-next-line no-param-reassign
    file.TypeInfoList = types;
    return hasOptimized;
}
function optimizeTypes(file) {
    let passes = 1;
    do {
        console.log(`Optimization pass #${passes++}`);
    } while (optimizeWorker(file));
    return passes > 1;
}
exports.optimizeTypes = optimizeTypes;
//# sourceMappingURL=OptimizeTypes.js.map