"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpMerge = void 0;
const AbstractOp_1 = require("./AbstractOp");
const json_pointer_1 = require("@jsonjoy.com/json-pointer");
const util_1 = require("../util");
const constants_1 = require("../constants");
/**
 * @category JSON Patch Extended
 */
class OpMerge extends AbstractOp_1.AbstractOp {
    constructor(path, pos, props) {
        super(path);
        this.pos = pos;
        this.props = props;
    }
    op() {
        return 'merge';
    }
    code() {
        return constants_1.OPCODE.merge;
    }
    apply(doc) {
        const ref = (0, json_pointer_1.find)(doc, this.path);
        if (!(0, json_pointer_1.isArrayReference)(ref))
            throw new Error('INVALID_TARGET');
        if (ref.key <= 0)
            throw new Error('INVALID_KEY');
        const one = ref.obj[ref.key - 1];
        const two = ref.obj[ref.key];
        const merged = this.merge(one, two);
        ref.obj[ref.key - 1] = merged;
        ref.obj.splice(ref.key, 1);
        return { doc, old: [one, two] };
    }
    merge(one, two) {
        if (typeof one === 'string' && typeof two === 'string')
            return one + two;
        if (typeof one === 'number' && typeof two === 'number')
            return one + two;
        if ((0, util_1.isTextNode)(one) && (0, util_1.isTextNode)(two))
            return { ...one, ...two, text: one.text + two.text };
        if ((0, util_1.isElementNode)(one) && (0, util_1.isElementNode)(two))
            return { ...one, ...two, children: [...one.children, ...two.children] };
        return [one, two];
    }
    toJson(parent) {
        const op = {
            op: 'merge',
            path: (0, json_pointer_1.formatJsonPointer)(this.path),
            pos: this.pos,
        };
        if (this.props)
            op.props = this.props;
        return op;
    }
    toCompact(parent, verbose) {
        const opcode = verbose ? 'merge' : constants_1.OPCODE.merge;
        return this.props ? [opcode, this.path, this.pos, this.props] : [opcode, this.path, this.pos];
    }
}
exports.OpMerge = OpMerge;
//# sourceMappingURL=OpMerge.js.map