"use strict";
/* eslint-disable max-classes-per-file */
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutputFilter = void 0;
const Utilities_1 = require("./Utilities");
class OutputFilter {
    constructor(file) {
        this.file = file;
        this.typesList = new Set();
        this.visitors = new Utilities_1.OncePer();
    }
    lookupType(type) {
        return this.file.TypeInfoList.find((typeDef) => typeDef.Type.TypeName === type.TypeName && typeDef.Type.Namespace === type.Namespace);
    }
    processRefs(visitor, ...typeRefs) {
        var _a, _b;
        for (const typeRef of typeRefs) {
            if (!typeRef) {
                continue;
            }
            if (!this.visitors.once(visitor, typeRef)) {
                continue;
            }
            const visitorResult = (_a = visitor.visitTypeUsage) === null || _a === void 0 ? void 0 : _a.call(visitor, typeRef);
            const typeDef = this.lookupType(typeRef);
            if (typeDef && visitorResult) {
                const nextVisitor = visitorResult === true ? visitor : visitorResult;
                this.typesList.add(typeDef);
                this.includeReferences(nextVisitor, typeDef);
            }
            this.processRefs(visitor, ...((_b = typeRef.TypeArguments) !== null && _b !== void 0 ? _b : []), typeDef === null || typeDef === void 0 ? void 0 : typeDef.Type.BaseType);
        }
        return this;
    }
    includeReferences(visitor, typeDef) {
        var _a, _b, _c, _d;
        if (!this.visitors.once(visitor, typeDef)) {
            return this;
        }
        this.processRefs(visitor, typeDef.Type, ...((_b = (_a = typeDef.StaticFields) === null || _a === void 0 ? void 0 : _a.map((field) => field.Type)) !== null && _b !== void 0 ? _b : []), ...((_d = (_c = typeDef.Fields) === null || _c === void 0 ? void 0 : _c.map((field) => field.Type)) !== null && _d !== void 0 ? _d : []));
        return this;
    }
    include(visitor) {
        var _a, _b;
        for (const type of this.file.TypeInfoList) {
            const visitorResult = (_a = visitor.visitType) === null || _a === void 0 ? void 0 : _a.call(visitor, type);
            if (visitorResult) {
                const nextVisitor = visitorResult === true ? visitor : visitorResult;
                this.typesList.add(type);
                this.includeReferences(nextVisitor, type);
            }
            if (type.NestedTypes) {
                for (const nestedType of type.NestedTypes) {
                    const nestedVisitorResult = (_b = visitor.visitType) === null || _b === void 0 ? void 0 : _b.call(visitor, nestedType);
                    if (nestedVisitorResult) {
                        const nextVisitor = nestedVisitorResult === true ? visitor : nestedVisitorResult;
                        this.typesList.add(nestedType);
                        this.includeReferences(nextVisitor, nestedType);
                    }
                }
            }
        }
        return this;
    }
}
exports.OutputFilter = OutputFilter;
//# sourceMappingURL=OutputFilter.js.map