import type Cdn from '../Loaders/Cdn';
import type { FirstChunkProbeRegistry, FirstChunkProbeSettings } from './FirstChunkProbe';
/**
 * @file Central peak-bandwidth sampler. Mirrors Android `ActiveSwitcher`'s
 * peak-sampler scope (plugin-android@video-balancer-24-2-on-main).
 *
 * One sampler per balancer instance. Each in-flight CDN request carries a
 * BandwidthSampleTag that records observedBytes / readCount. The sampler
 * ticks every `tickMs` after a `warmupMs` delay, groups active tags by Cdn,
 * sums the bytes, and publishes a peak bandwidth (bits/sec) onto the Cdn.
 *
 * Peak is consumed only as a fallback when the EMA bandwidth is null. It is
 * also published at call close (`publishOnClose`) when both byte and read
 * thresholds are met.
 */
export interface PeakSamplerSettings {
    /** Initial delay before the first tick fires. */
    warmupMs: number;
    /** Sampling cadence after the warm-up. */
    tickMs: number;
    /** Minimum xhr.onprogress events for a tag to qualify before warm-up. */
    minReadsForEarlySample: number;
    /** Minimum bytes a tag must have observed to qualify for sampling at all. */
    minBytesPerCall: number;
}
export declare const DEFAULT_PEAK_SAMPLER_SETTINGS: PeakSamplerSettings;
export interface BandwidthSampleTag {
    cdn: Cdn;
    startMs: number;
    observedBytes: number;
    readCount: number;
}
type NowFn = () => number;
type SettingsSource = Partial<PeakSamplerSettings> | (() => Partial<PeakSamplerSettings> | undefined);
/**
 * Per-balancer-instance central sampler. Started lazily on the first
 * registerActiveCall and stopped when the last call unregisters.
 *
 * Settings are read live: pass a getter at construction time and the sampler
 * resolves the current PeakSamplerSettings on every operation. This way
 * customData updates that mutate `BalancerOptions.peakSampler` take effect
 * without re-instantiating the sampler.
 */
export default class PeakBandwidthSampler {
    private readonly settingsSource;
    private readonly nowFn;
    private readonly tags;
    private warmupTimer;
    private tickTimer;
    private running;
    private armedTickMs;
    private firstChunkRegistry?;
    private firstChunkSettingsSource?;
    constructor(settings?: SettingsSource, now?: NowFn);
    /**
     * Wire a first-chunk probe registry into the sampler. Called once at
     * balancer construction. The settings source is read live (same pattern
     * as the peak-sampler settings) so customData updates apply at the next
     * tick.
     */
    attachFirstChunkProbe(registry: FirstChunkProbeRegistry, settings?: Partial<FirstChunkProbeSettings> | (() => Partial<FirstChunkProbeSettings> | undefined)): void;
    private getFirstChunkSettings;
    /** Resolve the current effective settings (defaults + caller overrides). */
    getSettings(): PeakSamplerSettings;
    /**
     * Register a freshly-dispatched call. Creates a sample tag rooted at the
     * caller-supplied Cdn. Returns the tag so the caller can update its byte
     * counter on every progress event.
     */
    registerActiveCall(xhr: XMLHttpRequest, cdn: Cdn): BandwidthSampleTag;
    /**
     * Notify that a call ended. Publishes a final peak sample on close when
     * both byte and read thresholds are met (Android `publishOnClose`). Stops
     * the central timer when no calls remain.
     */
    unregisterActiveCall(xhr: XMLHttpRequest): void;
    /** Update a tag's byte / read counters. Called from xhr.onprogress. */
    recordProgress(xhr: XMLHttpRequest, observedBytes: number): void;
    /** Immediate snapshot of the live tag for a given XHR (tests / diagnostics). */
    getTag(xhr: XMLHttpRequest): BandwidthSampleTag | undefined;
    /** Number of in-flight tracked calls. Tests + diagnostics. */
    size(): number;
    /** Force a tick. Test hook; in production the timer fires it. */
    tick(): void;
    /**
     * First-chunk probe abort evaluation (Android ActiveSwitcher.evaluateFirstChunkAborts).
     * For each registered probe with enough samples + a known Content-Length,
     * compute observedBps vs the requiredBps to clear the remaining bytes
     * within the remaining time. Abort when observedBps * safetyFactor falls
     * short. Idempotent via the `cancelled` flag.
     */
    private evaluateFirstChunkAborts;
    /** Stop the timer and clear all tags. Used at balancer destroy. */
    destroy(): void;
    private publishOnClose;
    private isReadyForSampling;
    private startTimer;
    private stopTimer;
    private static defaultNow;
}
export {};
