"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compactToPredicateOp = exports.compactToOp = void 0;
exports.decode = decode;
const OpAdd_1 = require("../../op/OpAdd");
const OpRemove_1 = require("../../op/OpRemove");
const OpReplace_1 = require("../../op/OpReplace");
const OpMove_1 = require("../../op/OpMove");
const OpCopy_1 = require("../../op/OpCopy");
const OpTest_1 = require("../../op/OpTest");
const OpFlip_1 = require("../../op/OpFlip");
const OpInc_1 = require("../../op/OpInc");
const OpStrIns_1 = require("../../op/OpStrIns");
const OpStrDel_1 = require("../../op/OpStrDel");
const OpSplit_1 = require("../../op/OpSplit");
const OpMerge_1 = require("../../op/OpMerge");
const OpExtend_1 = require("../../op/OpExtend");
const OpDefined_1 = require("../../op/OpDefined");
const OpUndefined_1 = require("../../op/OpUndefined");
const OpTestType_1 = require("../../op/OpTestType");
const OpTestString_1 = require("../../op/OpTestString");
const OpTestStringLen_1 = require("../../op/OpTestStringLen");
const OpContains_1 = require("../../op/OpContains");
const OpEnds_1 = require("../../op/OpEnds");
const OpStarts_1 = require("../../op/OpStarts");
const OpIn_1 = require("../../op/OpIn");
const OpLess_1 = require("../../op/OpLess");
const OpMore_1 = require("../../op/OpMore");
const OpAnd_1 = require("../../op/OpAnd");
const OpOr_1 = require("../../op/OpOr");
const OpNot_1 = require("../../op/OpNot");
const OpMatches_1 = require("../../op/OpMatches");
const OpType_1 = require("../../op/OpType");
const json_pointer_1 = require("@jsonjoy.com/json-pointer");
const constants_1 = require("../../constants");
const util_1 = require("../../util");
const compactToOp = (op, options) => {
    switch (op[0]) {
        case constants_1.OPCODE.add:
        case 'add':
            return new OpAdd_1.OpAdd((0, json_pointer_1.toPath)(op[1]), op[2]);
        case constants_1.OPCODE.remove:
        case 'remove':
            return new OpRemove_1.OpRemove((0, json_pointer_1.toPath)(op[1]), op[2]);
        case constants_1.OPCODE.replace:
        case 'replace':
            return new OpReplace_1.OpReplace((0, json_pointer_1.toPath)(op[1]), op[2], op[3]);
        case constants_1.OPCODE.move:
        case 'move':
            return new OpMove_1.OpMove((0, json_pointer_1.toPath)(op[1]), (0, json_pointer_1.toPath)(op[2]));
        case constants_1.OPCODE.copy:
        case 'copy':
            return new OpCopy_1.OpCopy((0, json_pointer_1.toPath)(op[1]), (0, json_pointer_1.toPath)(op[2]));
        case constants_1.OPCODE.flip:
        case 'flip':
            return new OpFlip_1.OpFlip((0, json_pointer_1.toPath)(op[1]));
        case constants_1.OPCODE.inc:
        case 'inc':
            return new OpInc_1.OpInc((0, json_pointer_1.toPath)(op[1]), op[2]);
        case constants_1.OPCODE.str_ins:
        case 'str_ins':
            return new OpStrIns_1.OpStrIns((0, json_pointer_1.toPath)(op[1]), op[2], op[3]);
        case constants_1.OPCODE.str_del:
        case 'str_del':
            return new OpStrDel_1.OpStrDel((0, json_pointer_1.toPath)(op[1]), op[2], op[3] || undefined, op[4]);
        case constants_1.OPCODE.split:
        case 'split':
            return new OpSplit_1.OpSplit((0, json_pointer_1.toPath)(op[1]), op[2], op[3] || null);
        case constants_1.OPCODE.merge:
        case 'merge':
            return new OpMerge_1.OpMerge((0, json_pointer_1.toPath)(op[1]), op[2], op[3] || null);
        case constants_1.OPCODE.extend:
        case 'extend':
            return new OpExtend_1.OpExtend((0, json_pointer_1.toPath)(op[1]), op[2], !!op[3]);
        default:
            return (0, exports.compactToPredicateOp)(op, options);
    }
};
exports.compactToOp = compactToOp;
const compactToPredicateOp = (op, options) => {
    switch (op[0]) {
        case constants_1.OPCODE.test:
        case 'test':
            return new OpTest_1.OpTest((0, json_pointer_1.toPath)(op[1]), op[2], !!op[3]);
        case constants_1.OPCODE.defined:
        case 'defined':
            return new OpDefined_1.OpDefined((0, json_pointer_1.toPath)(op[1]));
        case constants_1.OPCODE.undefined:
        case 'undefined':
            return new OpUndefined_1.OpUndefined((0, json_pointer_1.toPath)(op[1]));
        case constants_1.OPCODE.type:
        case 'type':
            return new OpType_1.OpType((0, json_pointer_1.toPath)(op[1]), op[2]);
        case constants_1.OPCODE.test_type:
        case 'test_type':
            return new OpTestType_1.OpTestType((0, json_pointer_1.toPath)(op[1]), op[2]);
        case constants_1.OPCODE.test_string:
        case 'test_string':
            return new OpTestString_1.OpTestString((0, json_pointer_1.toPath)(op[1]), op[2], op[3], !!op[4]);
        case constants_1.OPCODE.test_string_len:
        case 'test_string_len':
            return new OpTestStringLen_1.OpTestStringLen((0, json_pointer_1.toPath)(op[1]), op[2], !!op[3]);
        case constants_1.OPCODE.contains:
        case 'contains':
            return new OpContains_1.OpContains((0, json_pointer_1.toPath)(op[1]), op[2], !!op[3]);
        case constants_1.OPCODE.ends:
        case 'ends':
            return new OpEnds_1.OpEnds((0, json_pointer_1.toPath)(op[1]), op[2], !!op[3]);
        case constants_1.OPCODE.starts:
        case 'starts':
            return new OpStarts_1.OpStarts((0, json_pointer_1.toPath)(op[1]), op[2], !!op[3]);
        case constants_1.OPCODE.matches:
        case 'matches':
            return new OpMatches_1.OpMatches((0, json_pointer_1.toPath)(op[1]), op[2], !!op[3], options.createMatcher || util_1.createMatcherDefault);
        case constants_1.OPCODE.in:
        case 'in':
            return new OpIn_1.OpIn((0, json_pointer_1.toPath)(op[1]), op[2]);
        case constants_1.OPCODE.less:
        case 'less':
            return new OpLess_1.OpLess((0, json_pointer_1.toPath)(op[1]), op[2]);
        case constants_1.OPCODE.more:
        case 'more':
            return new OpMore_1.OpMore((0, json_pointer_1.toPath)(op[1]), op[2]);
        case constants_1.OPCODE.and:
        case 'and': {
            const path = (0, json_pointer_1.toPath)(op[1]);
            return new OpAnd_1.OpAnd(path, op[2].map((x) => {
                const copy = [...x];
                copy[1] = [...path, ...(0, json_pointer_1.toPath)(x[1])];
                return (0, exports.compactToPredicateOp)(copy, options);
            }));
        }
        case constants_1.OPCODE.or:
        case 'or': {
            const path = (0, json_pointer_1.toPath)(op[1]);
            return new OpOr_1.OpOr(path, op[2].map((x) => {
                const copy = [...x];
                copy[1] = [...path, ...(0, json_pointer_1.toPath)(x[1])];
                return (0, exports.compactToPredicateOp)(copy, options);
            }));
        }
        case constants_1.OPCODE.not:
        case 'not': {
            const path = (0, json_pointer_1.toPath)(op[1]);
            return new OpNot_1.OpNot(path, op[2].map((x) => {
                const copy = [...x];
                copy[1] = [...path, ...(0, json_pointer_1.toPath)(x[1])];
                return (0, exports.compactToPredicateOp)(copy, options);
            }));
        }
        default:
            throw new Error('OP_UNKNOWN');
    }
};
exports.compactToPredicateOp = compactToPredicateOp;
function decode(patch, options) {
    const ops = [];
    const length = patch.length;
    for (let i = 0; i < length; i++) {
        const op = (0, exports.compactToOp)(patch[i], options);
        ops.push(op);
    }
    return ops;
}
//# sourceMappingURL=decode.js.map