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