/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { assert } from "@fluidframework/core-utils/internal";
import { BaseSegment } from "./mergeTreeNodes.js";
// Maximum length of text segment to be considered to be merged with other segment.
// Maximum segment length is at least 2x of it (not taking into account initial segment creation).
// The bigger it is, the more expensive it is to break segment into sub-segments (on edits)
// The smaller it is, the more segments we have in snapshots (and in memory) - it's more expensive to load snapshots.
// Small number also makes ReplayTool produce false positives ("same" snapshots have slightly different binary
// representations).  More measurements needs to be done, but it's very likely the right spot is somewhere between
// 1K-2K mark.  That said, we also break segments on newline and there are very few segments that are longer than 256
// because of it.  Must be an even number.
// Exported for test use only.
export const TextSegmentGranularity = 256;
/**
 * @legacy
 * @alpha
 */
export class TextSegment extends BaseSegment {
    static is(segment) {
        return segment.type === TextSegment.type;
    }
    static make(text, props) {
        return new TextSegment(text, props);
    }
    static fromJSONObject(spec) {
        if (typeof spec === "string") {
            return new TextSegment(spec);
        }
        else if (spec && typeof spec === "object" && "text" in spec) {
            const textSpec = spec;
            return TextSegment.make(textSpec.text, textSpec.props);
        }
        return undefined;
    }
    constructor(text, props) {
        super(props);
        this.text = text;
        this.type = TextSegment.type;
        this.cachedLength = text.length;
    }
    toJSONObject() {
        // To reduce snapshot/ops size, we serialize a TextSegment as a plain 'string' if it is
        // not annotated.
        return this.properties ? { text: this.text, props: { ...this.properties } } : this.text;
    }
    clone(start = 0, end) {
        const text = this.text.slice(start, end);
        const b = TextSegment.make(text, this.properties);
        this.cloneInto(b);
        return b;
    }
    canAppend(segment) {
        return (!this.text.endsWith("\n") &&
            TextSegment.is(segment) &&
            (this.cachedLength <= TextSegmentGranularity ||
                segment.cachedLength <= TextSegmentGranularity));
    }
    toString() {
        return this.text;
    }
    append(segment) {
        assert(TextSegment.is(segment), 0x447 /* can only append text segment */);
        super.append(segment);
        this.text += segment.text;
    }
    createSplitSegmentAt(pos) {
        if (pos > 0) {
            const remainingText = this.text.slice(Math.max(0, pos));
            this.text = this.text.slice(0, Math.max(0, pos));
            this.cachedLength = this.text.length;
            const leafSegment = new TextSegment(remainingText);
            return leafSegment;
        }
    }
}
TextSegment.type = "TextSegment";
//# sourceMappingURL=textSegment.js.map