// SPDX-License-Identifier: Apache-2.0
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var ClassToObjectMapper_1;
import { instanceToPlain, plainToInstance } from 'class-transformer';
import { ObjectMappingError } from '../api/object-mapping-error.js';
import { inject, injectable } from 'tsyringe-neo';
import { InjectTokens } from '../../../core/dependency-injection/inject-tokens.js';
import { FlatKeyMapper } from './flat-key-mapper.js';
import { patchInject } from '../../../core/dependency-injection/container-helper.js';
import { IllegalArgumentError } from '../../../business/errors/illegal-argument-error.js';
let ClassToObjectMapper = ClassToObjectMapper_1 = class ClassToObjectMapper {
    formatter;
    flatMapper;
    constructor(formatter) {
        this.formatter = formatter;
        this.flatMapper = new FlatKeyMapper(patchInject(formatter, InjectTokens.KeyFormatter, ClassToObjectMapper_1.name));
    }
    fromArray(cls, array) {
        const result = [];
        for (const item of array) {
            result.push(this.fromObject(cls, item));
        }
        return result;
    }
    fromObject(cls, object) {
        try {
            return plainToInstance(cls, object);
        }
        catch (error) {
            throw new ObjectMappingError(`Error converting object to class instance [ cls = '${cls.name}' ]`, error);
        }
    }
    toArray(data) {
        const result = [];
        for (const item of data) {
            result.push(this.toObject(item));
        }
        return result;
    }
    toObject(data) {
        try {
            return instanceToPlain(data);
        }
        catch (error) {
            throw new ObjectMappingError(`Error converting class instance to object [ cls = '${data.constructor.name}' ]`, error);
        }
    }
    toFlatKeyMap(data) {
        return this.flatMapper.flatten(data);
    }
    applyPropertyValue(object, key, value) {
        if (!object) {
            throw new IllegalArgumentError('obj must not be null or undefined');
        }
        if (!key) {
            throw new IllegalArgumentError('key must not be null or undefined');
        }
        const normalizedKey = this.formatter.normalize(key);
        const components = this.formatter.split(normalizedKey);
        let currentObject = object;
        for (let index = 0; index < components.length - 1; index++) {
            const keyComponent = components[index];
            // If the property is not found, we cannot proceed.
            if (!(keyComponent in currentObject)) {
                throw new ObjectMappingError(`Property not found [ key = '${key}', obj = '${currentObject}' ]`);
            }
            const propertyType = typeof currentObject[keyComponent];
            // If we are at the end of the key path, then set the property.
            // Otherwise, the property must be an object.
            if (index === components.length - 1) {
                currentObject[keyComponent] = value;
            }
            else if (propertyType !== 'object' || Array.isArray(currentObject[keyComponent])) {
                throw new ObjectMappingError(`Non-terminal property is not an object [ key = '${key}', propertyType = '${propertyType}' ]`);
            }
            currentObject = currentObject[keyComponent];
            // If the current object is null or undefined, we cannot proceed.
            if (currentObject === undefined || currentObject === null) {
                throw new ObjectMappingError(`Intermediate object must not be null or undefined [ key = '${key}' ]`);
            }
        }
    }
};
ClassToObjectMapper = ClassToObjectMapper_1 = __decorate([
    injectable(),
    __param(0, inject(InjectTokens.KeyFormatter)),
    __metadata("design:paramtypes", [Object])
], ClassToObjectMapper);
export { ClassToObjectMapper };
//# sourceMappingURL=class-to-object-mapper.js.map