import { tick } from '../../../json-crdt-patch/clock';
import { AbstractRga } from '../rga/AbstractRga';
/**
 * @ignore
 * @category CRDT Node
 */
export class BinChunk {
    id;
    span;
    del;
    data;
    len;
    p;
    l;
    r;
    p2;
    l2;
    r2;
    s;
    constructor(id, span, buf) {
        this.id = id;
        this.span = span;
        this.len = buf ? span : 0;
        this.del = !buf;
        this.p = undefined;
        this.l = undefined;
        this.r = undefined;
        this.s = undefined;
        this.data = buf;
    }
    merge(data) {
        const length = this.data.length;
        const combined = new Uint8Array(length + data.length);
        combined.set(this.data);
        combined.set(data, length);
        this.data = combined;
        this.span = combined.length;
    }
    split(ticks) {
        if (!this.del) {
            const data = this.data;
            const rightBuffer = data.subarray(ticks);
            const chunk = new BinChunk(tick(this.id, ticks), this.span - ticks, rightBuffer);
            this.data = data.subarray(0, ticks);
            this.span = ticks;
            return chunk;
        }
        const chunk = new BinChunk(tick(this.id, ticks), this.span - ticks, undefined);
        this.span = ticks;
        return chunk;
    }
    delete() {
        this.del = true;
        this.data = undefined;
    }
    clone() {
        const chunk = new BinChunk(this.id, this.span, this.data);
        return chunk;
    }
    view() {
        return this.data || new Uint8Array(0);
    }
}
/**
 * Represents the `bin` type in JSON CRDT. The `bin` is a blob of binary data,
 * powered by a Replicated Growable Array (RGA) algorithm.
 *
 * @category CRDT Node
 */
export class BinNode extends AbstractRga {
    // ----------------------------------------------------------------- JsonNode
    /** @ignore */
    _view = null;
    view() {
        if (this._view)
            return this._view;
        const res = new Uint8Array(this.length());
        let offset = 0;
        let chunk = this.first();
        while (chunk) {
            if (!chunk.del) {
                const buf = chunk.data;
                res.set(buf, offset);
                offset += buf.length;
            }
            chunk = this.next(chunk);
        }
        return (this._view = res);
    }
    /** @ignore */
    children() { }
    /** @ignore */
    child() {
        return undefined;
    }
    /** @ignore */
    container() {
        return undefined;
    }
    /** @ignore */
    api = undefined;
    name() {
        return 'bin';
    }
    // -------------------------------------------------------------- AbstractRga
    /** @ignore */
    createChunk(id, buf) {
        return new BinChunk(id, buf ? buf.length : 0, buf);
    }
    /** @ignore */
    onChange() {
        this._view = null;
    }
    toStringName() {
        return this.name();
    }
}
//# sourceMappingURL=BinNode.js.map