// SPDX-License-Identifier: Apache-2.0
import { Version } from '../../../../business/utils/version.js';
import { SchemaValidationError } from './schema-validation-error.js';
export class SchemaDefinitionBase {
    mapper;
    constructor(mapper) {
        this.mapper = mapper;
    }
    async transform(data, sourceVersion) {
        if (data === undefined || data === null) {
            return null;
        }
        const clone = structuredClone(data);
        let dataVersion = clone.schemaVersion;
        if (!dataVersion) {
            dataVersion = sourceVersion ? sourceVersion.value : 0;
        }
        const migrated = await this.applyMigrations(clone, new Version(dataVersion));
        return this.mapper.fromObject(this.classConstructor, migrated);
    }
    async validateMigrations() {
        if (this.migrations.length === 0) {
            return;
        }
        const versionJumps = this.migrations.map(value => value.version.value).sort();
        for (let index = 1; index < versionJumps.length; index++) {
            if (versionJumps[index] === versionJumps[index - 1]) {
                throw new SchemaValidationError(`Duplicate migration version '${versionJumps[index]}'`);
            }
        }
        let currentVersion = this.nextVersionJump(new Version(0));
        for (const versionJump of versionJumps) {
            const v = new Version(versionJump);
            if (!v.equals(currentVersion)) {
                throw new SchemaValidationError(`Invalid migration version sequence detected; expected version '${v.value}' but got '${currentVersion.value}'`);
            }
            currentVersion = this.nextVersionJump(currentVersion);
        }
        return;
    }
    nextVersionJump(currentVersion) {
        const targetMigrations = this.findMigrations(currentVersion);
        if (!targetMigrations || targetMigrations.length === 0) {
            // No migration found for the current version - fail with an error
            throw new SchemaValidationError(`No migration found for version '${currentVersion.value}'; there is a gap in the migration sequence`);
        }
        return targetMigrations[0].version;
    }
    /*
     * DV < version = 1 >
     * M1 < range = [0, 6), version = 6 >
     * M1.1 < range = [0, 4), version = 5 >
     * M2 < range = [6, 7), version = 8 >
     */
    async applyMigrations(data, dataVersion) {
        let migrations = this.findMigrations(dataVersion);
        while (migrations.length > 0) {
            const migration = migrations[0];
            data = await migration.migrate(data);
            dataVersion = migration.version;
            migrations = this.findMigrations(dataVersion);
        }
        return data;
    }
    findMigrations(dataVersion) {
        const eligibleMigrations = this.migrations.filter(value => value.range.contains(dataVersion));
        if (eligibleMigrations.length > 0) {
            eligibleMigrations.sort((l, r) => l.version.compare(r.version));
        }
        return eligibleMigrations;
    }
}
//# sourceMappingURL=schema-definition-base.js.map