import { CONST, updateNum } from '../json-hash/hash';
import { ConNode, ValNode, ObjNode, VecNode, ArrNode } from './nodes';
import { AbstractRga } from './nodes/rga';
import { last2 } from 'sonic-forest/lib/util2';
export const updateId = (state, id) => {
    const time = id.time;
    state = updateNum(state, state ^ time);
    state = updateNum(state, id.sid ^ time);
    return state;
};
export const updateRga = (state, node) => {
    state = updateNum(state, node.length());
    state = updateNum(state, node.size());
    const maxIdChunk = last2(node.ids);
    if (maxIdChunk)
        state = updateId(state, maxIdChunk.id);
    return updateId(state, node.id);
};
/**
 * Updates the hash state with the given JSON CRDT node.
 * @param state Current hash state.
 * @param node JSON CRDT node from which to compute the hash.
 */
export const updateNode = (state, node) => {
    if (node instanceof ConNode)
        return updateId(state, node.id);
    if (node instanceof ValNode) {
        const child = node.child();
        if (child)
            state = updateNode(state, child);
        return updateId(state, node.id);
    }
    if (node instanceof ObjNode || node instanceof VecNode) {
        node.children((child) => {
            state = updateNode(state, child);
        });
        return updateId(state, node.id);
    }
    if (node instanceof ArrNode) {
        node.children((child) => {
            state = updateNode(state, child);
        });
    }
    if (node instanceof AbstractRga)
        return updateRga(state, node);
    throw new Error('UNKNOWN_NODE');
};
export const hashId = (id) => {
    return updateId(CONST.START_STATE, id);
};
export const hashNode = (node) => {
    return updateNode(CONST.START_STATE, node) >>> 0;
};
export const hashModel = (model) => {
    return hashNode(model.root);
};
//# sourceMappingURL=hash.js.map