"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.compareRevisions = exports.subtractChangeAtomIds = exports.newChangeAtomIdRangeMap = exports.mintCommit = exports.CommitKind = exports.replaceAtomRevisions = exports.offsetChangeAtomId = exports.taggedOptAtomId = exports.taggedAtomId = exports.asChangeAtomId = exports.makeChangeAtomId = exports.areEqualChangeAtomIdOpts = exports.areEqualChangeAtomIds = exports.RevisionTagSchema = exports.SessionIdSchema = void 0;
const typebox_1 = 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 = typebox_1.Type.Union([
    typebox_1.Type.Literal("root"),
    (0, index_js_1.brandedNumberType)(),
]);
/**
 * @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;
function replaceAtomRevisions(id, oldRevisions, newRevision) {
    return oldRevisions.has(id.revision) ? atomWithRevision(id, newRevision) : id;
}
exports.replaceAtomRevisions = replaceAtomRevisions;
function atomWithRevision(id, revision) {
    const updated = { ...id, revision };
    if (revision === undefined) {
        delete updated.revision;
    }
    return updated;
}
/**
 * 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() {
    return new index_js_1.RangeMap(offsetChangeAtomId, subtractChangeAtomIds);
}
exports.newChangeAtomIdRangeMap = newChangeAtomIdRangeMap;
function subtractChangeAtomIds(a, b) {
    const cmp = compareRevisions(a.revision, b.revision);
    if (cmp !== 0) {
        return cmp * Number.POSITIVE_INFINITY;
    }
    return a.localId - b.localId;
}
exports.subtractChangeAtomIds = subtractChangeAtomIds;
function compareRevisions(a, b) {
    if (a === undefined) {
        return b === undefined ? 0 : -1;
    }
    else if (b === undefined) {
        return 1;
    }
    else if (a < b) {
        return -1;
    }
    else if (a > b) {
        return 1;
    }
    return 0;
}
exports.compareRevisions = compareRevisions;
//# sourceMappingURL=types.js.map