/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
/**
 * A `SynchronizedClock` allows for approximating the time on a remote machine.
 *
 * During initialization, a known time of the remote host must be supplied. Once
 * the remote time is known, this class can approximate the time on the remote
 * machine from a date or duration.
 *
 * @example
 * ```
 * const knownRemoteTime = await getRemoteTime();
 * const clock = new SynchronizedClock(knownRemoteTime);
 *
 * const localDate = new Date();
 * const serverTime = clock.remoteTime(localDate);
 *
 * const remoteDate = await getRemoteTime();
 * const localTime = clock.localTime(remoteDate);
 *
 * const currentRemoteTime = clock.remoteNow();
 * ```
 */
export class SynchronizedClock {
    constructor(knownRemoteTime, knownLocalTime = new Date()) {
        this.knownRemoteTime = knownRemoteTime;
        this.knownLocalTime = knownLocalTime;
    }
    /**
     * Computes an offset duration from when this clock was instantiated.
     */
    localOffset() {
        return this.duration(this.knownLocalTime, this.localNow());
    }
    /**
     * Approximates the local time from a remote timestamp or duration.
     *
     * @param remoteTimeOrDurationInMs A remote timestamp or duration.
     */
    localTime(remoteTimeOrDurationInMs) {
        const remoteTime = typeof remoteTimeOrDurationInMs === 'number'
            ? new Date(this.knownLocalTime.getTime() + remoteTimeOrDurationInMs)
            : remoteTimeOrDurationInMs;
        const duration = this.duration(this.knownRemoteTime, remoteTime);
        return this.addDuration(this.knownLocalTime, duration);
    }
    /**
     * Approximates an offset duration on the remote machine.
     *
     * @param localTime A local timestamp. Defaults to the current local time.
     */
    remoteOffset(localTime = new Date()) {
        return this.duration(this.remoteTime(this.knownLocalTime), this.remoteTime(localTime));
    }
    /**
     * Approximates the current time on the remote machine.
     */
    remoteNow() {
        return this.remoteTime(this.localNow());
    }
    /**
     * Approximates the remote time from either a local timestamp or duration.
     *
     * @param localTimeOrDurationInMs A local timestamp or duration.
     */
    remoteTime(localTimeOrDurationInMs) {
        const localTime = typeof localTimeOrDurationInMs === 'number'
            ? new Date(this.knownLocalTime.getTime() + localTimeOrDurationInMs)
            : localTimeOrDurationInMs;
        const duration = this.duration(this.knownLocalTime, localTime);
        return this.addDuration(this.knownRemoteTime, duration);
    }
    addDuration(start, duration) {
        return new Date(start.getTime() + duration);
    }
    duration(start, end) {
        return end.getTime() - start.getTime();
    }
    localNow() {
        return new Date(Date.now());
    }
}
//# sourceMappingURL=synchronizedClock.js.map
