"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NestedTag = void 0;
const json_crdt_patch_1 = require("../../../json-crdt-patch");
const model_1 = require("../../../json-crdt/model");
/**
 * Represents a single nested tag in a slice type. For example, in a slice type
 * like `['<blockquote>', 0, {author: 'Alice'}, ['<p>', 0, {indent: 2}]]`, there
 * is a tag for the blockquote and a tag for the paragraph. Each tag can
 * contain a discriminant and data.
 */
class NestedTag {
    constructor(type, index) {
        this.type = type;
        this.index = index;
    }
    /**
     * Enforces current tag at `index` to be a "vec" node, which contains
     * a tag, a discriminant and an object with data.
     */
    asVec() {
        const arr = this.type.asArr();
        const typeLen = arr.length();
        let index = this.index;
        if (typeof index !== 'number' || index > typeLen - 1)
            index = typeLen - 1;
        const vec = arr.get(index);
        if (vec instanceof model_1.VecApi)
            return vec;
        const tag = vec instanceof model_1.ConApi ? vec.view() : 0;
        arr.upd(index, json_crdt_patch_1.s.vec(json_crdt_patch_1.s.con(tag)));
        return arr.get(index);
    }
    /**
     * Returns the tag name at the current index, which is either a string or a number.
     * If the tag is not set, it returns `0`.
     *
     * @returns The tag value.
     */
    name() {
        const vec = this.asVec();
        const tag = vec.select(0)?.view();
        return typeof tag === 'string' || typeof tag === 'number' ? tag : 0;
    }
    /**
     * Sets the tag name at the current index. If the tag is not a string or a number,
     * it will be converted to a string.
     *
     * @param tag - The tag value to set.
     */
    setName(tag) {
        const vec = this.asVec();
        vec.set([[0, json_crdt_patch_1.s.con(tag)]]);
    }
    /**
     * Returns the discriminant of the tag at the current index.
     * If the discriminant is not set, it returns `0`.
     *
     * @returns The discriminant value.
     */
    discriminant() {
        const disciminant = this.asVec().select(1)?.view() || 0;
        return typeof disciminant === 'number' ? disciminant : 0;
    }
    /**
     * Sets the discriminant of the tag at the current index.
     *
     * @param value - The discriminant value to set.
     */
    setDiscriminant(value) {
        const vec = this.asVec();
        vec.set([[1, json_crdt_patch_1.s.con(value)]]);
    }
    /**
     * Returns the data object of the tag at the current index.
     * If the data is not set, it returns an empty object. Enforces the
     * data to be a {@link ObjApi} node, use this API to manipulate the data
     * object.
     *
     * @returns The data object.
     */
    data() {
        const vec = this.asVec();
        const data = vec.select(2);
        if (data instanceof model_1.ObjApi)
            return data;
        vec.set([[2, json_crdt_patch_1.s.obj({})]]);
        return vec.get(2);
    }
}
exports.NestedTag = NestedTag;
//# sourceMappingURL=NestedTag.js.map