/**
 * Per-tick recording of replicated component state for snapshot interpolation.
 *
 * Two ring buffers — both wrap at tick boundaries only:
 *
 *   - `__buffer` (BinaryBuffer): raw component bytes, written via `begin_record`
 *     / `end_record`. Variable size per record.
 *
 *   - `__records` (Uint32Array): the metadata table, holding one row per
 *     `(network_id, type_id, byte_offset, byte_length)` plus a bloom-filter
 *     header every {@link METADATA_PAGE_SIZE} records. The structure:
 *
 *       page = [bloom_0..7] [rec_0_n, _t, _o, _l] ... [rec_38_n, _t, _o, _l]
 *
 *     A new page header is written at `begin_tick` and then again every 39
 *     records within a tick. The bloom filter is keyed by `network_id`, so a
 *     `locate(network_id, type_id)` can skip whole pages with a single 256-bit
 *     check before falling back to a per-record scan inside the page. Pages
 *     never straddle tick boundaries.
 *
 * Per-tick metadata is small: byte range + word range in `__records` + record
 * count. The oldest tick is tracked explicitly (`__oldest_tick`) so the squash
 * check at each {@link begin_tick} is amortized O(1) — squash the oldest while
 * it overlaps the new write region, advance the pointer, repeat.
 *
 * Pair with {@link BinaryInterpolationAdapter} concrete subclasses (e.g.
 * {@link Vector3InterpolationAdapter}) which know each component type's
 * encoding and blend math.
 *
 * Typical receive-side use:
 * ```
 *   onFrameApplied(_, frame_number) {
 *       log.begin_tick(frame_number);
 *       const buf = log.begin_record(network_id, type_id);
 *       adapter.serialize(buf, value);
 *       log.end_record();
 *       log.end_tick();
 *   }
 * ```
 *
 * Typical render-time use:
 * ```
 *   const ok = log.interpolate(out_buffer, network_id, type_id, tick_a, tick_b, t, adapter);
 *   if (ok) { /* deserialize from out_buffer into the live component }
 * ```
 *
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2025
 */
export class InterpolationLog {
    /**
     * @param {{ buffer_capacity_bytes?: number, records_capacity?: number }} [options]
     *   `records_capacity` is in *records* (not bytes); the underlying word
     *   array is sized large enough to fit that many records plus their pages'
     *   bloom-filter headers.
     */
    constructor({ buffer_capacity_bytes, records_capacity }?: {
        buffer_capacity_bytes?: number;
        records_capacity?: number;
    });
    /** @readonly @type {number} */
    readonly buffer_capacity: number;
    /** @readonly @type {number} */
    readonly records_capacity: number;
    /**
     * Open a new tick for recording. May wrap either ring at this point — but
     * never mid-tick, so a single tick's data is always contiguous in both
     * the byte buffer and the metadata table. After wrapping, any old tick
     * whose data overlaps the new write region is squashed (in oldest-first
     * order) and `__oldest_tick` advances.
     *
     * @param {number} tick non-negative integer
     */
    begin_tick(tick: number): void;
    /**
     * Begin recording one component. Returns the underlying byte buffer
     * positioned at the next write slot — the caller writes the component
     * payload directly (e.g. via a `BinaryClassSerializationAdapter.serialize`
     * call), then calls {@link end_record} to finalize the (offset, length).
     *
     * Splitting begin/end (vs. taking a write callback) avoids the per-record
     * closure allocation and lets the caller pass the buffer straight to an
     * adapter without wrapping.
     *
     * @param {number} network_id
     * @param {number} type_id component type id (small integer; matches the registry)
     * @returns {BinaryBuffer} the log's byte buffer, positioned for writing the payload
     */
    begin_record(network_id: number, type_id: number): BinaryBuffer;
    /**
     * Finalize the in-progress record opened by {@link begin_record}. Reads
     * the buffer's current position to compute the payload length, inserts
     * the network_id into the current page's bloom filter, writes the row to
     * the metadata table, and advances the cursors.
     */
    end_record(): void;
    /**
     * Close the currently-open tick. Updates the max-observed-tick sizes so
     * the next {@link begin_tick} can size its wrap heuristic correctly.
     *
     * Throws if a record is still open — silently dropping the in-progress
     * record's metadata (offset/length) would leak buffer space and produce
     * stale bytes that no one can locate.
     */
    end_tick(): void;
    /**
     * @param {number} tick
     * @returns {boolean} true if the tick has live (non-squashed) data
     */
    has_tick(tick: number): boolean;
    /**
     * Find a component's stored slice within a tick. Walks the tick's pages,
     * bloom-filter-skipping pages that don't contain `network_id`, and
     * scanning records inside any page where the bloom hits.
     *
     * On success, writes `out[out_offset+0] = byte_offset` and
     * `out[out_offset+1] = byte_length`.
     *
     * @param {number[]|Uint32Array} out
     * @param {number} out_offset
     * @param {number} tick
     * @param {number} network_id
     * @param {number} type_id
     * @returns {boolean} false if the tick is missing/squashed or doesn't carry this component
     */
    locate(out: number[] | Uint32Array, out_offset: number, tick: number, network_id: number, type_id: number): boolean;
    /**
     * Interpolate one component between two ticks via `adapter` and write the
     * result to `out_buffer` at its current position.
     *
     * Outcome by available data:
     *   - Both ticks carry the component → adapter blends them at `t`.
     *   - Only one carries it → adapter is called with the same offset twice
     *     (snap to the surviving snapshot; `t` is irrelevant).
     *   - Neither carries it → returns false; `out_buffer` is unchanged.
     *
     * @param {BinaryBuffer} out_buffer
     * @param {number} network_id
     * @param {number} type_id
     * @param {number} tick_a
     * @param {number} tick_b
     * @param {number} t
     * @param {BinaryInterpolationAdapter} adapter
     * @returns {boolean} true if a payload was written; false if neither tick has the component
     */
    interpolate(out_buffer: BinaryBuffer, network_id: number, type_id: number, tick_a: number, tick_b: number, t: number, adapter: BinaryInterpolationAdapter): boolean;
    /**
     * Number of ticks currently held. Squashed ticks are excluded.
     * @returns {number}
     */
    size(): number;
    /**
     * Tick number of the oldest live tick, or -1 if empty.
     * @returns {number}
     */
    oldest_tick(): number;
    /**
     * Drop all recorded ticks. Resets both ring cursors to 0. Useful on
     * reconnect or level transition.
     */
    clear(): void;
    #private;
}
import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
//# sourceMappingURL=InterpolationLog.d.ts.map