"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchemaRegistry = exports.SchemaNodeKind = void 0;
var SchemaNodeKind;
(function (SchemaNodeKind) {
    SchemaNodeKind["CATALOG"] = "catalog";
    SchemaNodeKind["DATABASE"] = "database";
    SchemaNodeKind["TABLE"] = "table";
    SchemaNodeKind["VIEW"] = "view";
    SchemaNodeKind["COLUMN"] = "column";
    SchemaNodeKind["FUNCTION"] = "function";
})(SchemaNodeKind = exports.SchemaNodeKind || (exports.SchemaNodeKind = {}));
class SchemaRegistry {
    constructor() {
        this.defaultDatabases = new Map();
        this._schemaNodes = [];
    }
    getSchemas(kind) {
        return kind ? this._schemaNodes.filter(n => n.kind === kind) : this._schemaNodes;
    }
    getSchemaCatalogs() {
        return this._schemaNodes.filter(n => n.kind === SchemaNodeKind.CATALOG);
    }
    getSchemaDatabases(schema = {}) {
        const catalog = schema.catalog ?? this.defaultCatalog;
        return this._schemaNodes.filter(n => n.kind === SchemaNodeKind.DATABASE && (catalog === undefined || n.catalog === catalog));
    }
    getSchemaTables(schema = {}) {
        const catalog = schema.catalog ?? this.defaultCatalog;
        const database = schema.database ?? (catalog && this.defaultDatabases.get(catalog));
        return this._schemaNodes.filter(n => n.kind === SchemaNodeKind.TABLE &&
            (catalog === undefined || n.catalog === catalog) &&
            (database === undefined || n.database === database));
    }
    getSchemaColumns(schema = {}) {
        const catalog = schema.catalog ?? this.defaultCatalog;
        const database = schema.database ?? (catalog && this.defaultDatabases.get(catalog));
        return this._schemaNodes.filter(n => n.kind === SchemaNodeKind.COLUMN &&
            (catalog === undefined || n.catalog === catalog) &&
            (database === undefined || n.database === database) &&
            (schema.table === undefined || n.table === schema.table));
    }
    getSchemaViews(schema = {}) {
        const catalog = schema.catalog ?? this.defaultCatalog;
        const database = schema.database ?? (catalog && this.defaultDatabases.get(catalog));
        return this._schemaNodes.filter(n => n.kind === SchemaNodeKind.VIEW &&
            (catalog === undefined || n.catalog === catalog) &&
            (database === undefined || n.database === database));
    }
    getSchemaFunctions(schema = {}) {
        const catalog = schema.catalog ?? this.defaultCatalog;
        const database = schema.database ?? (catalog && this.defaultDatabases.get(catalog));
        return this._schemaNodes.filter(n => n.kind === SchemaNodeKind.FUNCTION &&
            (catalog === undefined || n.catalog === catalog) &&
            (database === undefined || n.database === database));
    }
    register(registerMode, schemas) {
        if (registerMode === 'set') {
            this._schemaNodes = [];
            this.defaultCatalog = undefined;
            this.defaultDatabases = new Map();
        }
        if (schemas.catalogs?.length) {
            this.registerCatalogs(registerMode, ...schemas.catalogs);
        }
        if (schemas.databases?.length) {
            this.registerDatabases(registerMode, ...schemas.databases);
        }
        if (schemas.tables?.length) {
            this.registerTables(registerMode, ...schemas.tables);
        }
        if (schemas.columns?.length) {
            this.registerColumns(registerMode, ...schemas.columns);
        }
        if (schemas.views?.length) {
            this.registerViews(registerMode, ...schemas.views);
        }
        if (schemas.functions?.length) {
            this.registerFunctions(registerMode, ...schemas.functions);
        }
    }
    registerCatalogs(registerMode, ...catalogs) {
        catalogs.forEach(c => {
            const node = {
                kind: SchemaNodeKind.CATALOG,
                label: c.label,
                description: c.description
            };
            if (registerMode === 'set') {
                this._schemaNodes.push(node);
            }
            else {
                const duplicate = this._schemaNodes.find(n => n.kind === SchemaNodeKind.CATALOG && n.label === c.label);
                if (!duplicate) {
                    this._schemaNodes.push(node);
                }
                else {
                    duplicate.description = c.description;
                }
            }
            if (c.default) {
                this.defaultCatalog = c.label;
            }
        });
    }
    registerDatabases(registerMode, ...databases) {
        databases.forEach(d => {
            const node = {
                kind: SchemaNodeKind.DATABASE,
                catalog: d.catalog,
                label: d.label,
                description: d.description
            };
            if (registerMode === 'set') {
                this._schemaNodes.push(node);
            }
            else {
                const duplicate = this._schemaNodes.find(n => n.kind === SchemaNodeKind.DATABASE && n.label === d.label && n.catalog === d.catalog);
                if (!duplicate) {
                    this._schemaNodes.push(node);
                }
                else {
                    duplicate.description = d.description;
                }
            }
            if (d.default) {
                this.defaultDatabases.set(d.catalog, d.label);
            }
        });
    }
    registerTables(registerMode, ...tables) {
        tables.forEach(t => {
            const node = {
                kind: SchemaNodeKind.TABLE,
                catalog: t.catalog,
                database: t.database,
                label: t.label,
                description: t.description
            };
            if (registerMode === 'set') {
                this._schemaNodes.push(node);
            }
            else {
                const duplicate = this._schemaNodes.find(n => n.kind === SchemaNodeKind.TABLE &&
                    n.label === t.label &&
                    n.catalog === t.catalog &&
                    n.database === t.database);
                if (!duplicate) {
                    this._schemaNodes.push(node);
                }
                else {
                    duplicate.description = t.description;
                }
            }
        });
    }
    registerColumns(registerMode, ...columns) {
        columns.forEach(c => {
            const node = {
                kind: SchemaNodeKind.COLUMN,
                catalog: c.catalog,
                database: c.database,
                table: c.table,
                label: c.label,
                description: c.description
            };
            if (registerMode === 'set') {
                this._schemaNodes.push(node);
            }
            else {
                const duplicate = this._schemaNodes.find(n => n.kind === SchemaNodeKind.COLUMN &&
                    n.label === c.label &&
                    n.catalog === c.catalog &&
                    n.database === c.database &&
                    n.table === c.table);
                if (!duplicate) {
                    this._schemaNodes.push(node);
                }
                else {
                    duplicate.description = c.description;
                }
            }
        });
    }
    registerViews(registerMode, ...views) {
        views.forEach(v => {
            const node = {
                kind: SchemaNodeKind.VIEW,
                catalog: v.catalog,
                database: v.database,
                label: v.label,
                description: v.description
            };
            if (registerMode === 'set') {
                this._schemaNodes.push(node);
            }
            else {
                const duplicate = this._schemaNodes.find(n => n.kind === SchemaNodeKind.VIEW &&
                    n.label === v.label &&
                    n.catalog === v.catalog &&
                    n.database === v.database);
                if (!duplicate) {
                    this._schemaNodes.push(node);
                }
            }
        });
    }
    registerFunctions(registerMode, ...functions) {
        functions.forEach(f => {
            const node = {
                kind: SchemaNodeKind.FUNCTION,
                catalog: f.catalog,
                database: f.database,
                label: f.label,
                description: f.description
            };
            if (registerMode === 'set') {
                this._schemaNodes.push(node);
            }
            else {
                const duplicate = this._schemaNodes.find(n => n.kind === SchemaNodeKind.FUNCTION &&
                    n.label === f.label &&
                    n.catalog === f.catalog &&
                    n.database === f.database);
                if (!duplicate) {
                    this._schemaNodes.push(node);
                }
            }
        });
    }
}
exports.SchemaRegistry = SchemaRegistry;
//# sourceMappingURL=schema-registry.js.map