"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.comparePartialRevisions = exports.subtractChangeAtomIds = exports.newChangeAtomIdRangeMap = exports.mintCommit = exports.CommitKind = exports.comparePartialChangesetLocalIds = exports.compareChangesetLocalIds = exports.offsetChangeAtomId = exports.taggedOptAtomId = exports.taggedAtomId = exports.asChangeAtomId = exports.makeChangeAtomId = exports.areEqualChangeAtomIdOpts = exports.areEqualChangeAtomIds = exports.StableIdSchema = exports.RevisionTagSchema = exports.SessionIdSchema = void 0;
const Type = __importStar(require("@sinclair/typebox"));
const index_js_1 = require("../../util/index.js");
/**
 * The identifier for a particular session/user/client that can generate `GraphCommit`s
 */
exports.SessionIdSchema = (0, index_js_1.brandedStringType)();
exports.RevisionTagSchema = Type.Union([
    Type.Literal("root"),
    (0, index_js_1.brandedNumberType)(),
]);
exports.StableIdSchema = Type.String();
/**
 * Returns true iff `a` and `b` are the same.
 */
function areEqualChangeAtomIds(a, b) {
    return a.localId === b.localId && a.revision === b.revision;
}
exports.areEqualChangeAtomIds = areEqualChangeAtomIds;
function areEqualChangeAtomIdOpts(a, b) {
    if (a === undefined || b === undefined) {
        return a === b;
    }
    return areEqualChangeAtomIds(a, b);
}
exports.areEqualChangeAtomIdOpts = areEqualChangeAtomIdOpts;
/**
 * Returns a ChangeAtomId with the given revision and local ID.
 */
function makeChangeAtomId(localId, revision) {
    return revision === undefined ? { localId } : { localId, revision };
}
exports.makeChangeAtomId = makeChangeAtomId;
function asChangeAtomId(id) {
    return typeof id === "object" ? id : { localId: id };
}
exports.asChangeAtomId = asChangeAtomId;
function taggedAtomId(id, revision) {
    return makeChangeAtomId(id.localId, id.revision ?? revision);
}
exports.taggedAtomId = taggedAtomId;
function taggedOptAtomId(id, revision) {
    if (id === undefined) {
        return undefined;
    }
    return taggedAtomId(id, revision);
}
exports.taggedOptAtomId = taggedOptAtomId;
function offsetChangeAtomId(id, offset) {
    return { ...id, localId: (0, index_js_1.brand)(id.localId + offset) };
}
exports.offsetChangeAtomId = offsetChangeAtomId;
// #region These comparison functions are used instead of e.g. `compareNumbers` as a performance optimization
function compareChangesetLocalIds(a, b) {
    return a - b; // No need to consider `NaN` or `Infinity` since ChangesetLocalId is always a real number
}
exports.compareChangesetLocalIds = compareChangesetLocalIds;
function comparePartialChangesetLocalIds(a, b) {
    if (a === undefined) {
        return b === undefined ? 0 : -1;
    }
    else if (b === undefined) {
        return 1;
    }
    return compareChangesetLocalIds(a, b);
}
exports.comparePartialChangesetLocalIds = comparePartialChangesetLocalIds;
/**
 * The type of a commit. This is used to describe the context in which the commit was created.
 *
 * @public
 */
var CommitKind;
(function (CommitKind) {
    /** A commit corresponding to a change that is not the result of an undo/redo from this client. */
    CommitKind[CommitKind["Default"] = 0] = "Default";
    /** A commit that is the result of an undo from this client. */
    CommitKind[CommitKind["Undo"] = 1] = "Undo";
    /** A commit that is the result of a redo from this client. */
    CommitKind[CommitKind["Redo"] = 2] = "Redo";
})(CommitKind || (exports.CommitKind = CommitKind = {}));
/**
 * Creates a new graph commit object. This is useful for creating copies of commits with different parentage.
 * @param parent - the parent of the new commit
 * @param commit - the contents of the new commit object
 * @returns the new commit object
 */
// Note that this function is synchronous, and therefore it is not a Promise.
// However, it is still a strong commit-mint.
function mintCommit(parent, commit) {
    const { revision, change } = commit;
    return {
        revision,
        change,
        parent,
    };
}
exports.mintCommit = mintCommit;
function newChangeAtomIdRangeMap(offsetValue) {
    return new index_js_1.RangeMap(offsetChangeAtomId, subtractChangeAtomIds, offsetValue);
}
exports.newChangeAtomIdRangeMap = newChangeAtomIdRangeMap;
function subtractChangeAtomIds(a, b) {
    const cmp = comparePartialRevisions(a.revision, b.revision);
    if (cmp !== 0) {
        return cmp * Number.POSITIVE_INFINITY;
    }
    return a.localId - b.localId;
}
exports.subtractChangeAtomIds = subtractChangeAtomIds;
/**
 * Compares two {@link RevisionTag}s to form a strict total ordering.
 * @remarks This function tolerates arbitrary strings, not just the string "root".
 * It sorts as follows: `undefined` \< `string` \< `number`
 */
function comparePartialRevisions(a, b) {
    if (typeof a === "number") {
        return typeof b === "number" ? a - b : 1;
    }
    else if (typeof b === "number") {
        return -1;
    }
    return (0, index_js_1.comparePartialStrings)(a, b);
}
exports.comparePartialRevisions = comparePartialRevisions;
//# sourceMappingURL=types.js.map