"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveOptions = exports.configuredSharedTreeInternal = exports.configuredSharedTree = exports.configuredSharedTreeAlpha = exports.configuredSharedTreeBetaLegacy = exports.configuredSharedTreeBeta = exports.SharedTree = void 0;
const internal_1 = require("@fluidframework/shared-object-base/internal");
const internal_2 = require("@fluidframework/telemetry-utils/internal");
const index_js_1 = require("./codec/index.js");
const index_js_2 = require("./shared-tree/index.js");
const index_js_3 = require("./shared-tree-core/index.js");
const sharedTreeAttributes_js_1 = require("./sharedTreeAttributes.js");
const index_js_4 = require("./util/index.js");
/**
 * Creates a factory for shared tree kernels with the given options.
 * @remarks
 * Exposes {@link ITreePrivate} to allow access to internals in tests without a cast.
 * Code exposing this beyond this package will need to update to a more public type.
 */
function treeKernelFactory(options) {
    function treeFromKernelArgs(args) {
        if (args.idCompressor === undefined) {
            throw new internal_2.UsageError("IdCompressor must be enabled to use SharedTree");
        }
        const { minVersionForCollab, ...otherOptions } = options;
        const adjustedOptions = {
            ...otherOptions,
            // Cases:
            // A. If options specifies minVersionForCollab, it takes precedence over args.minVersionForCollab.
            // This value is set when:
            // - A customer using the declarative SharedTree API specifies the setting at the Shared Tree level.
            //   There is currently no way to set it via the declarative API, but it could be added in the future.
            // - treeKernelFactory is invoked in a fuzz test with a specific minVersionForCollab
            // B. Otherwise, we use args.minVersionForCollab, which is propagated from the ContainerRuntime.
            // C. If neither specifies it, we fall back to a default value default of 2.0 since that is the oldest version that supports SharedTree.
            minVersionForCollab: minVersionForCollab ?? args.minVersionForCollab ?? index_js_1.FluidClientVersion.v2_0,
        };
        return new index_js_2.SharedTreeKernel(new index_js_4.Breakable("SharedTree"), args.sharedObject, args.serializer, args.submitLocalMessage, args.lastSequenceNumber, args.initialSequenceNumber, args.logger, args.idCompressor, adjustedOptions);
    }
    return {
        create: (args) => {
            const k = treeFromKernelArgs(args);
            return { kernel: k, view: k.view };
        },
        async loadCore(args, storage) {
            const k = treeFromKernelArgs(args);
            await k.loadCore(storage);
            return { kernel: k, view: k.view };
        },
    };
}
/**
 * SharedTree is a hierarchical data structure for collaboratively editing strongly typed JSON-like trees
 * of objects, arrays, and other data types.
 * @legacy @beta
 */
exports.SharedTree = configuredSharedTree({});
/**
 * {@link SharedTree} but allowing a non-default configuration.
 * @remarks
 * This is useful for debugging and testing.
 * For example it can be used to opt into extra validation or see if opting out of some optimizations fixes an issue.
 *
 * With great care, and knowledge of the support and stability of the options exposed here,
 * this can also be used to opt into some features early or for performance tuning.
 *
 * @example
 * ```typescript
 * import {
 * 	configuredSharedTreeBeta,
 * 	ForestTypeReference,
 * } from "fluid-framework/beta";
 * const SharedTree = configuredSharedTree({
 * 	forest: ForestTypeReference,
 * });
 * ```
 * @privateRemarks
 * The Legacy `ISharedObjectKind<ITree>` type is omitted here for simplicity.
 * @beta
 */
function configuredSharedTreeBeta(options) {
    return configuredSharedTree(options);
}
exports.configuredSharedTreeBeta = configuredSharedTreeBeta;
/**
 * {@link configuredSharedTreeBeta} including the legacy `ISharedObjectKind` type.
 * @privateRemarks
 * This is given a different export name (with legacy appended) to avoid the need to do the special reexport with different types from the fluid-framework package.
 * @legacy @beta
 */
function configuredSharedTreeBetaLegacy(options) {
    return configuredSharedTree(options);
}
exports.configuredSharedTreeBetaLegacy = configuredSharedTreeBetaLegacy;
/**
 * {@link configuredSharedTreeBeta} but including the alpha {@link SharedTreeOptions}.
 * @alpha
 */
function configuredSharedTreeAlpha(options) {
    return configuredSharedTree(options);
}
exports.configuredSharedTreeAlpha = configuredSharedTreeAlpha;
/**
 * {@link configuredSharedTreeBetaLegacy} but including `@alpha` options.
 *
 * @example
 * ```typescript
 * import {
 * 	TreeCompressionStrategy,
 * 	configuredSharedTree,
 * 	FormatValidatorBasic,
 * 	ForestTypeReference,
 * } from "@fluidframework/tree/internal";
 * const SharedTree = configuredSharedTree({
 * 	forest: ForestTypeReference,
 * 	jsonValidator: FormatValidatorBasic,
 * 	treeEncodeType: TreeCompressionStrategy.Uncompressed,
 * });
 * ```
 * @privateRemarks
 * This should be legacy, but has to be internal due to no alpha+legacy being setup yet.
 *
 * This should be renamed to `configuredSharedTreeAlpha` to avoid colliding with the eventual public version which will have less options.
 * @internal
 */
function configuredSharedTree(options) {
    const internalOptions = resolveOptions(options);
    return configuredSharedTreeInternal(internalOptions);
}
exports.configuredSharedTree = configuredSharedTree;
function configuredSharedTreeInternal(options) {
    const sharedObjectOptions = {
        type: sharedTreeAttributes_js_1.SharedTreeFactoryType,
        attributes: sharedTreeAttributes_js_1.SharedTreeAttributes,
        telemetryContextPrefix: "fluid_sharedTree_",
        factory: treeKernelFactory(options),
    };
    return (0, internal_1.makeSharedObjectKind)(sharedObjectOptions);
}
exports.configuredSharedTreeInternal = configuredSharedTreeInternal;
function resolveOptions(options) {
    const internal = {
        ...resolveFormatOptions(options),
    };
    for (const optionName of Object.keys(options)) {
        (0, index_js_4.copyProperty)(options, optionName, internal);
    }
    return internal;
}
exports.resolveOptions = resolveOptions;
function resolveFormatOptions(options) {
    const enableSharedBranches = options.enableSharedBranches ?? false;
    if (enableSharedBranches) {
        return sharedBranchesOptions;
    }
    return {};
}
const sharedBranchesOptions = {
    writeVersionOverrides: new Map([
        [index_js_3.editManagerCodecName, index_js_3.EditManagerFormatVersion.vSharedBranches],
        [index_js_3.messageCodecName, index_js_3.MessageFormatVersion.vSharedBranches],
    ]),
    allowPossiblyIncompatibleWriteVersionOverrides: true,
};
//# sourceMappingURL=treeFactory.js.map