import { compareStrings } from "../utils/StringComparison.js";
import GraphModelMigrationBasis from "./GraphModelMigrationBasis.js";
import GraphModelMigrationLoweredOperation from "./GraphModelMigrationLoweredOperation.js";
import WarpError from "../errors/WarpError.js";
/** Frozen write-ready migration patch plan for scratch writers. */
export default class GraphModelMigrationLoweredPatchPlan {
    sourceBasis;
    targetBasis;
    operations;
    constructor(fields) {
        const checkedFields = requireFields(fields);
        this.sourceBasis = requireBasis(checkedFields.sourceBasis, 'sourceBasis');
        this.targetBasis = requireBasis(checkedFields.targetBasis, 'targetBasis');
        this.operations = freezeOperations(checkedFields.operations);
        Object.freeze(this);
    }
    /** Returns true when the plan has at least one lowered write fact. */
    hasOperations() {
        return this.operations.length > 0;
    }
}
function requireFields(fields) {
    if (fields === null || fields === undefined) {
        throw new WarpError('GraphModelMigrationLoweredPatchPlan fields must be provided', 'E_VALIDATION');
    }
    return fields;
}
function requireBasis(basis, name) {
    if (!(basis instanceof GraphModelMigrationBasis)) {
        throw new WarpError(`${name} must be a GraphModelMigrationBasis`, 'E_VALIDATION');
    }
    return basis;
}
function freezeOperations(operations) {
    if (!Array.isArray(operations)) {
        throw new WarpError('operations must be an array', 'E_VALIDATION');
    }
    const checked = operations.map(requireOperation);
    requireUnique(checked.map((operation) => operation.toKey()));
    return Object.freeze([...checked].sort(compareOperations));
}
function requireOperation(operation) {
    if (!(operation instanceof GraphModelMigrationLoweredOperation)) {
        throw new WarpError('operations must contain lowered migration operations', 'E_VALIDATION');
    }
    return operation;
}
function requireUnique(keys) {
    const seen = new Set();
    for (const key of keys) {
        if (seen.has(key)) {
            throw new WarpError(`GraphModelMigrationLoweredPatchPlan duplicates operation ${key}`, 'E_VALIDATION');
        }
        seen.add(key);
    }
}
function compareOperations(left, right) {
    return compareStrings(left.toKey(), right.toKey());
}
