"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hashModel = exports.hashNode = exports.hashId = exports.updateNode = exports.updateRga = exports.updateId = void 0;
const hash_1 = require("../json-hash/hash");
const nodes_1 = require("./nodes");
const rga_1 = require("./nodes/rga");
const util2_1 = require("sonic-forest/lib/util2");
const updateId = (state, id) => {
    const time = id.time;
    state = (0, hash_1.updateNum)(state, state ^ time);
    state = (0, hash_1.updateNum)(state, id.sid ^ time);
    return state;
};
exports.updateId = updateId;
const updateRga = (state, node) => {
    state = (0, hash_1.updateNum)(state, node.length());
    state = (0, hash_1.updateNum)(state, node.size());
    const maxIdChunk = (0, util2_1.last2)(node.ids);
    if (maxIdChunk)
        state = (0, exports.updateId)(state, maxIdChunk.id);
    return (0, exports.updateId)(state, node.id);
};
exports.updateRga = updateRga;
/**
 * 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.
 */
const updateNode = (state, node) => {
    if (node instanceof nodes_1.ConNode)
        return (0, exports.updateId)(state, node.id);
    if (node instanceof nodes_1.ValNode) {
        const child = node.child();
        if (child)
            state = (0, exports.updateNode)(state, child);
        return (0, exports.updateId)(state, node.id);
    }
    if (node instanceof nodes_1.ObjNode || node instanceof nodes_1.VecNode) {
        node.children((child) => {
            state = (0, exports.updateNode)(state, child);
        });
        return (0, exports.updateId)(state, node.id);
    }
    if (node instanceof nodes_1.ArrNode) {
        node.children((child) => {
            state = (0, exports.updateNode)(state, child);
        });
    }
    if (node instanceof rga_1.AbstractRga)
        return (0, exports.updateRga)(state, node);
    throw new Error('UNKNOWN_NODE');
};
exports.updateNode = updateNode;
const hashId = (id) => {
    return (0, exports.updateId)(hash_1.CONST.START_STATE, id);
};
exports.hashId = hashId;
const hashNode = (node) => {
    return (0, exports.updateNode)(hash_1.CONST.START_STATE, node) >>> 0;
};
exports.hashNode = hashNode;
const hashModel = (model) => {
    return (0, exports.hashNode)(model.root);
};
exports.hashModel = hashModel;
//# sourceMappingURL=hash.js.map