// SPDX-License-Identifier: Apache-2.0
import { IllegalArgumentError } from '../../../business/errors/illegal-argument-error.js';
import { ConfigurationError } from '../api/configuration-error.js';
import { plainToInstance } from 'class-transformer';
import { ReflectAssist } from '../../../business/utils/reflect-assist.js';
export class LayeredConfigSource {
    backend;
    mapper;
    prefix;
    /**
     * The forest model of the configuration keys and values.
     * @protected
     */
    forest;
    constructor(backend, mapper, prefix) {
        this.backend = backend;
        this.mapper = mapper;
        this.prefix = prefix;
        if (!mapper) {
            throw new IllegalArgumentError('ObjectMapper is required');
        }
    }
    asBoolean(key) {
        const stringValue = this.forest.valueFor(key);
        if (!stringValue || stringValue.trim().length === 0) {
            return null;
        }
        const value = ReflectAssist.coerce(stringValue);
        if (typeof value === 'boolean') {
            return value;
        }
        else if (typeof value === 'string') {
            return value === 'true';
        }
        else if (typeof value === 'number') {
            return value !== 0;
        }
        else if (typeof value === 'object') {
            if (value === null || value === undefined) {
                return null;
            }
            return true;
        }
        throw new ConfigurationError('value is not a boolean');
    }
    asNumber(key) {
        const stringValue = this.forest.valueFor(key);
        if (!stringValue || stringValue.trim().length === 0) {
            return null;
        }
        const value = ReflectAssist.coerce(stringValue);
        if (typeof value === 'number') {
            return value;
        }
        else if (typeof value === 'object' && (value === null || value === undefined)) {
            return null;
        }
        throw new ConfigurationError('value is not a number');
    }
    asObject(cls, key) {
        if (!cls) {
            throw new ConfigurationError('class constructor is required');
        }
        try {
            let object = null;
            if (key) {
                const node = this.forest.nodeFor(key);
                if (!node) {
                    return null;
                }
                object = node.isLeaf() ? JSON.parse(node.value) : node.toObject();
            }
            else {
                object = this.forest.toObject();
            }
            return this.mapper.fromObject(cls, object);
        }
        catch (error) {
            throw new ConfigurationError('Failed to convert value to object', error);
        }
    }
    asObjectArray(cls, key) {
        if (!cls) {
            throw new ConfigurationError('class constructor is required');
        }
        if (!key) {
            throw new ConfigurationError('key is required');
        }
        const node = this.forest.nodeFor(key);
        if (!node) {
            return null;
        }
        if (!node.isArray()) {
            throw new ConfigurationError('value is not an array');
        }
        try {
            const objectArray = node.toObject();
            return plainToInstance(cls, objectArray);
        }
        catch (error) {
            throw new ConfigurationError('Failed to convert value to object array', error);
        }
    }
    asString(key) {
        return this.forest.valueFor(key) || null;
    }
    asStringArray(key) {
        if (!key) {
            throw new ConfigurationError('key is required');
        }
        const node = this.forest.nodeFor(key);
        if (!node) {
            return null;
        }
        if (!node.isArray()) {
            throw new ConfigurationError('value is not an array');
        }
        try {
            return node.toObject();
        }
        catch (error) {
            throw new ConfigurationError('Failed to convert value to object array', error);
        }
    }
    properties() {
        return new Map(this.forest.toFlatMap());
    }
    propertyNames() {
        return new Set(this.forest.toFlatMap().keys());
    }
}
//# sourceMappingURL=layered-config-source.js.map