"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decode = void 0;
const fromBase64_1 = require("@jsonjoy.com/base64/lib/fromBase64");
const clock_1 = require("../../clock");
const PatchBuilder_1 = require("../../PatchBuilder");
const timestamp = (sid, x) => {
    return Array.isArray(x) ? new clock_1.Timestamp(x[0], x[1]) : new clock_1.Timestamp(sid, x);
};
const timespan = (sid, span) => {
    return span.length === 3 ? new clock_1.Timespan(span[0], span[1], span[2]) : new clock_1.Timespan(sid, span[0], span[1]);
};
/**
 * Decodes a JSON CRDT Patch from a "compact" POJO into a {@link Patch} instance.
 *
 * @param data A JavaScript POJO array in the compact codec format.
 * @returns A decoded patch.
 */
const decode = (data) => {
    const header = data[0];
    const x = header[0];
    const clock = Array.isArray(x) ? new clock_1.ClockVector(x[0], x[1]) : new clock_1.ServerClockVector(1 /* SESSION.SERVER */, x);
    const sid = clock.sid;
    const _time = clock.time;
    const builder = new PatchBuilder_1.PatchBuilder(clock);
    const length = data.length;
    for (let i = 1; i < length; i++) {
        const op = data[i];
        switch (op[0]) {
            case 0 /* JsonCrdtPatchOpcode.new_con */: {
                const [, value, isTimestamp] = op;
                builder.con(isTimestamp ? timestamp(sid, value) : value);
                break;
            }
            case 1 /* JsonCrdtPatchOpcode.new_val */: {
                builder.val();
                break;
            }
            case 2 /* JsonCrdtPatchOpcode.new_obj */: {
                builder.obj();
                break;
            }
            case 3 /* JsonCrdtPatchOpcode.new_vec */: {
                builder.vec();
                break;
            }
            case 4 /* JsonCrdtPatchOpcode.new_str */: {
                builder.str();
                break;
            }
            case 5 /* JsonCrdtPatchOpcode.new_bin */: {
                builder.bin();
                break;
            }
            case 6 /* JsonCrdtPatchOpcode.new_arr */: {
                builder.arr();
                break;
            }
            case 9 /* JsonCrdtPatchOpcode.ins_val */: {
                builder.setVal(timestamp(sid, op[1]), timestamp(sid, op[2]));
                break;
            }
            case 10 /* JsonCrdtPatchOpcode.ins_obj */: {
                const obj = timestamp(sid, op[1]);
                const tuples = [];
                const value = op[2];
                const length = value.length;
                for (let j = 0; j < length; j++) {
                    const [key, x] = value[j];
                    tuples.push([key, timestamp(sid, x)]);
                }
                builder.insObj(obj, tuples);
                break;
            }
            case 11 /* JsonCrdtPatchOpcode.ins_vec */: {
                const obj = timestamp(sid, op[1]);
                const tuples = [];
                const value = op[2];
                const length = value.length;
                for (let j = 0; j < length; j++) {
                    const [key, x] = value[j];
                    tuples.push([key, timestamp(sid, x)]);
                }
                builder.insVec(obj, tuples);
                break;
            }
            case 12 /* JsonCrdtPatchOpcode.ins_str */: {
                builder.insStr(timestamp(sid, op[1]), timestamp(sid, op[2]), op[3]);
                break;
            }
            case 13 /* JsonCrdtPatchOpcode.ins_bin */: {
                builder.insBin(timestamp(sid, op[1]), timestamp(sid, op[2]), (0, fromBase64_1.fromBase64)(op[3]));
                break;
            }
            case 14 /* JsonCrdtPatchOpcode.ins_arr */: {
                const obj = timestamp(sid, op[1]);
                const ref = timestamp(sid, op[2]);
                const value = op[3];
                const elements = [];
                const length = value.length;
                for (let j = 0; j < length; j++)
                    elements.push(timestamp(sid, value[j]));
                builder.insArr(obj, ref, elements);
                break;
            }
            case 15 /* JsonCrdtPatchOpcode.upd_arr */: {
                const obj = timestamp(sid, op[1]);
                const ref = timestamp(sid, op[2]);
                const val = timestamp(sid, op[3]);
                builder.updArr(obj, ref, val);
                break;
            }
            case 16 /* JsonCrdtPatchOpcode.del */: {
                const obj = timestamp(sid, op[1]);
                const spans = op[2];
                const what = [];
                const length = spans.length;
                for (let i = 0; i < length; i++)
                    what.push(timespan(sid, spans[i]));
                builder.del(obj, what);
                break;
            }
            case 17 /* JsonCrdtPatchOpcode.nop */: {
                builder.nop(op[1] || 1);
                break;
            }
        }
    }
    const patch = builder.patch;
    patch.meta = header[1];
    return patch;
};
exports.decode = decode;
//# sourceMappingURL=decode.js.map