/**
 * ConflictResolvedCoordinate — runtime-backed analysis coordinate metadata.
 *
 * @module domain/types/conflict/ConflictResolvedCoordinate
 */
import WarpError from "../../errors/WarpError.js";
import StrandCoordinateMetadata from "./StrandCoordinateMetadata.js";
import { requireNonEmptyString, requireEnum } from "./validation.js";
const CTX = 'ConflictResolvedCoordinate';
const VALID_COORDINATE_KINDS = new Set(['frontier', 'strand']);
/**
 * Deep-freezes the frontier record.
 */
function freezeFrontier(frontier) {
    if (frontier === null || frontier === undefined || typeof frontier !== 'object') {
        throw new WarpError(`${CTX}: frontier must be an object`, 'E_VALIDATION');
    }
    return Object.freeze({ ...frontier });
}
/**
 * Deep-freezes the scan budget object.
 */
function freezeScanBudget(budget) {
    if (budget === null || budget === undefined || typeof budget !== 'object') {
        throw new WarpError(`${CTX}: scanBudgetApplied must be an object`, 'E_VALIDATION');
    }
    return Object.freeze({ maxPatches: budget.maxPatches });
}
/**
 * Normalizes the optional strand input into a
 * StrandCoordinateMetadata instance.
 */
function toStrandMetadata(strand) {
    if (strand === undefined || strand === null) {
        return undefined;
    }
    if (strand instanceof StrandCoordinateMetadata) {
        return strand;
    }
    return new StrandCoordinateMetadata(strand);
}
/**
 * A runtime-backed description of the analysis coordinate scope.
 *
 * Instances are frozen on construction. All nested objects are deep-frozen.
 */
export default class ConflictResolvedCoordinate {
    analysisVersion;
    coordinateKind;
    frontier;
    frontierDigest;
    lamportCeiling;
    scanBudgetApplied;
    truncationPolicy;
    strand;
    /**
     * Creates a frozen ConflictResolvedCoordinate.
     */
    constructor({ analysisVersion, coordinateKind, frontier, frontierDigest, lamportCeiling, scanBudgetApplied, truncationPolicy, strand }) {
        this.analysisVersion = requireNonEmptyString(analysisVersion, 'analysisVersion', CTX);
        this.coordinateKind = requireEnum(coordinateKind, VALID_COORDINATE_KINDS, { name: 'coordinateKind', context: CTX });
        this.frontier = freezeFrontier(frontier);
        this.frontierDigest = requireNonEmptyString(frontierDigest, 'frontierDigest', CTX);
        this.lamportCeiling = lamportCeiling;
        this.scanBudgetApplied = freezeScanBudget(scanBudgetApplied);
        this.truncationPolicy = requireNonEmptyString(truncationPolicy, 'truncationPolicy', CTX);
        this.strand = toStrandMetadata(strand);
        Object.freeze(this);
    }
}
