import QueryError from "../../errors/QueryError.js";
/** Runtime-backed native distinctions for a structural observer. */
export default class ObserverBasis {
    #distinctions;
    constructor(distinctions = []) {
        this.#distinctions = normalizeDistinctions(distinctions);
        Object.freeze(this);
    }
    static from(distinctions) {
        return new ObserverBasis(distinctions ?? []);
    }
    get distinctions() {
        return this.#distinctions;
    }
    get size() {
        return this.#distinctions.length;
    }
    isEmpty() {
        return this.#distinctions.length === 0;
    }
    contains(distinction) {
        return this.#distinctions.includes(distinction);
    }
    matchedBy(propertyKeys) {
        const keys = new Set(propertyKeys);
        return Object.freeze(this.#distinctions.filter((distinction) => keys.has(distinction)));
    }
    toConfigValue() {
        return [...this.#distinctions];
    }
}
function normalizeDistinctions(distinctions) {
    requireDistinctionArray(distinctions);
    const seen = new Set();
    const normalized = [];
    for (const distinction of distinctions) {
        normalized.push(requireDistinction(distinction, seen));
    }
    return Object.freeze(normalized);
}
function requireDistinctionArray(distinctions) {
    if (!Array.isArray(distinctions)) {
        throw new QueryError('observer basis must be an array of distinctions', {
            code: 'E_OBSERVER_BASIS_TYPE',
            context: { field: 'basis' },
        });
    }
}
function requireDistinction(distinction, seen) {
    if (typeof distinction !== 'string' || distinction.length === 0) {
        throw new QueryError('observer basis distinction must be non-empty', {
            code: 'E_OBSERVER_BASIS_DISTINCTION',
            context: { field: 'basis' },
        });
    }
    if (seen.has(distinction)) {
        throw new QueryError('observer basis distinction must be unique', {
            code: 'E_OBSERVER_BASIS_DISTINCTION',
            context: { field: 'basis', distinction },
        });
    }
    seen.add(distinction);
    return distinction;
}
