/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { brand, isReadonlyArray } from "../../util";
import { ModularChangeFamily, ModularEditBuilder, } from "../modular-schema";
import { fieldKinds, optional, sequence, value as valueFieldKind } from "./defaultFieldKinds";
/**
 * Implementation of {@link ChangeFamily} based on the default set of supported field kinds.
 *
 * @sealed
 */
export class DefaultChangeFamily {
    constructor(codecOptions) {
        this.modularFamily = new ModularChangeFamily(fieldKinds, codecOptions);
    }
    get rebaser() {
        return this.modularFamily.rebaser;
    }
    get codecs() {
        return this.modularFamily.codecs;
    }
    intoDelta(change) {
        return this.modularFamily.intoDelta(change);
    }
    buildEditor(changeReceiver, anchorSet) {
        return new DefaultEditBuilder(this, changeReceiver, anchorSet);
    }
}
/**
 * Implementation of {@link IDefaultEditBuilder} based on the default set of supported field kinds.
 * @sealed
 */
export class DefaultEditBuilder {
    constructor(family, changeReceiver, anchors) {
        this.modularBuilder = new ModularEditBuilder(family, changeReceiver, anchors);
    }
    enterTransaction() {
        this.modularBuilder.enterTransaction();
    }
    exitTransaction() {
        this.modularBuilder.exitTransaction();
    }
    apply(change) {
        this.modularBuilder.apply(change);
    }
    addNodeExistsConstraint(path) {
        this.modularBuilder.addNodeExistsConstraint(path);
    }
    valueField(field) {
        return {
            set: (newContent) => {
                const id = this.modularBuilder.generateId();
                const change = brand(valueFieldKind.changeHandler.editor.set(newContent, id));
                this.modularBuilder.submitChange(field, valueFieldKind.identifier, change);
            },
        };
    }
    optionalField(field) {
        return {
            set: (newContent, wasEmpty) => {
                const id = this.modularBuilder.generateId();
                const change = brand(optional.changeHandler.editor.set(newContent, wasEmpty, id));
                this.modularBuilder.submitChange(field, optional.identifier, change);
            },
        };
    }
    move(sourceField, sourceIndex, count, destinationField, destIndex) {
        const moveId = this.modularBuilder.generateId(count);
        const changes = sequence.changeHandler.editor.move(sourceIndex, count, destIndex, moveId);
        this.modularBuilder.submitChanges([
            {
                field: sourceField,
                fieldKind: sequence.identifier,
                change: brand(changes[0]),
            },
            {
                field: destinationField,
                fieldKind: sequence.identifier,
                change: brand(changes[1]),
            },
        ], moveId);
    }
    sequenceField(field) {
        return {
            insert: (index, newContent) => {
                const content = isReadonlyArray(newContent) ? newContent : [newContent];
                if (content.length === 0) {
                    return;
                }
                const length = Array.isArray(newContent) ? newContent.length : 1;
                const firstId = this.modularBuilder.generateId(length);
                const change = brand(sequence.changeHandler.editor.insert(index, content, firstId));
                this.modularBuilder.submitChange(field, sequence.identifier, change, brand(firstId + length - 1));
            },
            delete: (index, count) => {
                if (count === 0) {
                    return;
                }
                const id = this.modularBuilder.generateId(count);
                const change = brand(sequence.changeHandler.editor.delete(index, count, id));
                this.modularBuilder.submitChange(field, sequence.identifier, change);
            },
            move: (sourceIndex, count, destIndex) => {
                const moveId = this.modularBuilder.generateId(count);
                const moves = sequence.changeHandler.editor.move(sourceIndex, count, destIndex, moveId);
                this.modularBuilder.submitChanges([
                    {
                        field,
                        fieldKind: sequence.identifier,
                        change: brand(moves[0]),
                    },
                    {
                        field,
                        fieldKind: sequence.identifier,
                        change: brand(moves[1]),
                    },
                ], moveId);
            },
        };
    }
}
//# sourceMappingURL=defaultChangeFamily.js.map