import defaultCodec from "../../utils/defaultCodec.js";
import defaultCrypto from "../../utils/defaultCrypto.js";
import { decodeEdgeKey } from "../KeyCodec.js";
import WarpStateClass from "./WarpState.js";
/**
 * State serialization and hashing for the current WARP state
 *
 * Provides visibility predicates for determining what is visible in the graph,
 * canonical state serialization for deterministic hashing, and state hash computation.
 *
 * Current state uses ORSet-based state rather than LWW registers for nodeAlive/edgeAlive.
 *
 * @module StateSerializer
 * @see WARP Spec Section 8.3 (Visibility)
 * @see WARP Spec Section 10.3 (Canonical Serialization)
 */
// ============================================================================
// Visibility Predicates (WARP spec Section 8.3)
// ============================================================================
/**
 * Checks if a node is visible (present in the ORSet).
 */
export function nodeVisible(state, nodeId) {
    return state.nodeAlive.contains(nodeId);
}
/**
 * Checks if an edge is visible.
 * Edge is visible if: edge is in ORSet AND both endpoints are visible.
 */
export function edgeVisible(state, edgeKey) {
    if (!state.edgeAlive.contains(edgeKey)) {
        return false;
    }
    const { from, to } = decodeEdgeKey(edgeKey);
    return nodeVisible(state, from) && nodeVisible(state, to);
}
/**
 * Checks if a property is visible.
 * Property is visible if the owning node is visible.
 * Callers obtain entries from WarpState property iterators — prop existence is implied.
 */
export function propertyVisible(state, entry) {
    return nodeVisible(state, entry.nodeId);
}
/**
 * Serializes state to canonical CBOR bytes.
 * Only includes VISIBLE projection with stable ordering.
 */
export function serializeState(state, { codec } = {}) {
    const projection = projectState(state);
    return (codec ?? defaultCodec).encode(projection);
}
/**
 * Projects a materialized state into its visible graph projection.
 */
export function projectState(state) {
    const nodes = [...state.nodeAlive.elements()].sort();
    const visibleEdges = [];
    for (const edgeKey of state.edgeAlive.elements()) {
        if (edgeVisible(state, edgeKey)) {
            visibleEdges.push(decodeEdgeKey(edgeKey));
        }
    }
    visibleEdges.sort((a, b) => {
        if (a.from !== b.from) {
            return a.from < b.from ? -1 : 1;
        }
        if (a.to !== b.to) {
            return a.to < b.to ? -1 : 1;
        }
        return a.label < b.label ? -1 : a.label > b.label ? 1 : 0;
    });
    const visibleProps = [];
    for (const entry of WarpStateClass.nodePropertiesFromState(state)) {
        if (nodeVisible(state, entry.nodeId)) {
            visibleProps.push({ node: entry.nodeId, key: entry.key, value: entry.register.value });
        }
    }
    visibleProps.sort((a, b) => {
        if (a.node !== b.node) {
            return a.node < b.node ? -1 : 1;
        }
        return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
    });
    return { nodes, edges: visibleEdges, props: visibleProps };
}
/**
 * Computes SHA-256 hash of canonical state bytes.
 */
export async function computeStateHash(state, { crypto, codec } = {}) {
    const c = crypto ?? defaultCrypto;
    const serialized = serializeState(state, codec ? { codec } : {});
    return await c.hash('sha256', serialized);
}
/**
 * Deserializes state from CBOR bytes.
 * Note: This reconstructs the visible projection only.
 */
export function deserializeState(buffer, { codec } = {}) {
    const c = codec ?? defaultCodec;
    return c.decode(buffer);
}
// ============================================================================
// Full State Serialization (for BTR replay)
// ============================================================================
// Re-export from CheckpointSerializer for compatibility.
// Both BTR and Checkpoint use the same canonical full-state format.
export { serializeFullState, deserializeFullState, } from "./CheckpointSerializer.js";
