import P2PLoader from './P2PLoader';
import CDNLoader from './CDNLoader';
import BalancerOptions from '../Utils/Options';
import SegmentStorage from '../Storage/SegmentStorage';
import { VideoSegment } from '../Storage/VideoSegment';
import CdnBalancer from '../CdnBalancer';
import ResourceIdentifier from '../manifest/ResourceIdentifier';
import P2PManifestRegistry from './P2PManifestRegistry';
import { P2PSegmentIdResolver } from './P2PSegmentIdResolver';
import DiskSegmentStore from '../Storage/DiskSegmentStore';
/**
 * @class
 * @description Request load main class, it manages and chooses between CDN and P2P requests and evaluates the requests.
 * @exports Loader
 */
export default class Loader {
    private _accountCode;
    private _resource;
    private readonly resourceIdentifier;
    /**
     * V2 manifest registry: parses HLS/DASH manifests as they arrive, tracks
     * per-rendition bandwidth and the canonical SwarmIdentity used to join the
     * same P2P swarm as iOS / Android peers.
     */
    private readonly p2pManifestRegistry;
    /**
     * V2 segment identity resolver: delegates to the registry when available,
     * otherwise falls back to a URL-based canonical key. Produces the 32-hex
     * segmentIds exchanged over the wire with native peers.
     */
    private readonly p2pSegmentIdResolver;
    /**
     * V2 segment cache with ACQUIRING -> READY state machine and (where
     * supported) IndexedDB-backed persistence for cross-session seeding.
     */
    readonly diskSegmentStore: DiskSegmentStore;
    private readonly _options;
    private _balancerBusinessObject;
    private readonly statsReportBusinessObject;
    P2PLoader: P2PLoader;
    CDNLoader: CDNLoader;
    storage: SegmentStorage;
    private _segments;
    segmentsMap: Map<string, string>;
    uuid: string;
    private isEnabled;
    private apiHost;
    private manifestModelHits;
    private manifestFallbacks;
    /**
     * Constructs loader.
     * @param {BalancerOptions} options Options object.
     */
    constructor(accountCode: string, options: BalancerOptions, apiHost: string);
    getReportInterval(): number;
    private camelToSnake;
    loadCDNBalancerData(firstRequest?: boolean): void;
    /**
     * Chooses to request to CDN or P2P and manages the response calling the callback.
     * @param {URL} url URL object for the request.
     * @param {callback} callback Callback method to call back when loaded.F
     * @param {Object} headers Optional headers of the request.
     * @param {number} retries Number of retries before giving up to load a segment if it fails, optional.
     * @param {boolean} forceArrayBuffer False by default, set as true if is expected to get the manifest response
     * in ArrayBuffer format.
     * @public
     */
    processSegment(url: URL, download: boolean, callbacks: callback[], headers: {
        [key: string]: string;
    }, retries?: number, forceArrayBuffer?: boolean, stats?: fragStats): VideoSegment;
    /**
     * Android `P2pProvider.fetch` / iOS `P2PProvider.fetch` port:
     *   1. Local disk cache hit  -> serve immediately, no network.
     *   2. Swarm access denied   -> fall back to CDN.
     *   3. Leader election       -> if a peer owns the segment, request from them.
     *   4. Election window elapses with no candidate -> fall back to CDN.
     *
     * Runs as a detached Promise so `processSegment` keeps its sync contract
     * with the player's interceptor.
     */
    private _dispatchP2pV2Async;
    /**
     * Single entry point for P2P -> CDN transitions. Flips `useP2P` off,
     * re-asks CDNLoader for a URL and registers the segment as an active CDN
     * request so the existing XHR retry machinery picks it up. The switch
     * counter is incremented at most once per segment (idempotent via
     * `segment.p2pSwitchRecorded`), so repeated V2/V1 fallbacks for the same
     * segment never double-count. Call sites are expected to set
     * `segment.p2pFailureReason` before calling so the reason is consumed
     * here rather than passed as a parameter; unset defaults to `'errors'`.
     * Returns `true` when a CDN URL was assigned and the caller can proceed
     * with the HTTP request, `false` otherwise.
     */
    _fallBackP2pToCdn(segment: VideoSegment): boolean;
    onProcessSegmentFail(segment: VideoSegment, retry: boolean): void;
    onProcessSegmentSuccess(segment: VideoSegment): void;
    /**
     * Returns the map of unfinished/active CDN requests.
     * @returns {Map<string,VideoSegment>} The map with the requests.
     * @public
     */
    enableCDN(name: string, enabled: boolean): boolean;
    setActive(name: string, enabled: boolean): boolean;
    setMaxBandwith(name: string, bandwidth: number): boolean;
    onAbort(xhr: XMLHttpRequest, segment: VideoSegment): void;
    /**
     * Arm the connect and total timers for one CDN attempt. Each provider hop
     * uses a fresh XHR so both timers naturally reset per provider (matches
     * Android CdnTimeoutSettings: totalTimeout is per-attempt, not per-session).
     * Values <= 0 mean "no deadline" — the corresponding timer is not armed.
     *
     * When `probeOverrides` is supplied (PR6 first-chunk probe), the connect
     * and total timers use those stricter values instead of the defaults.
     */
    armAttemptTimers(xhr: XMLHttpRequest, segment: VideoSegment, probeOverrides?: {
        connectTimeoutMs: number;
        totalDownloadTimeoutMs: number;
    }): void;
    /**
     * Re-arm the read timeout. Read timeout is "between socket reads" — armed at
     * HEADERS_RECEIVED and re-armed on every progress tick. <= 0 disables.
     */
    armReadTimeout(xhr: XMLHttpRequest, segment: VideoSegment): void;
    clearConnectTimer(xhr: XMLHttpRequest): void;
    /**
     * Recompute the trial call deadline from the announced Content-Length, the
     * current good CDN's bandwidth, and that CDN's idle ratio (L0). Replaces
     * the active total-attempt timer ONLY when the new deadline is stricter
     * than the baseline already armed (Android parity:
     * TrialDeadlineEventListener.responseHeadersEnd, "stricter only" guard).
     *
     * NOTE: the Android impl reads L0 from a single global StatsCollector
     * shared across all providers; the JS impl tracks concurrency per-Cdn.
     * For the trial decision the current CDN's idle fraction is the relevant
     * signal (it's the CDN we're protecting from underrun) so the divergence
     * is benign in `cdnPriority`/single-CDN-active modes — and a closer match
     * to the writeup's intent ("CDN idle") than a global aggregate would be.
     */
    private _recomputeTrialDeadline;
    clearAttemptTimers(xhr: XMLHttpRequest, segment: VideoSegment): void;
    loadEM(xhr: XMLHttpRequest, url: URL, e: ProgressEvent): void;
    loadStartEM(xhr: XMLHttpRequest, segment: VideoSegment, e: ProgressEvent): void;
    progressEM(xhr: XMLHttpRequest, segment: VideoSegment, e: ProgressEvent): void;
    readyStateChangeEM(xhr: XMLHttpRequest, segment: VideoSegment, cdnBalancer: CdnBalancer): boolean;
    timeout(xhr: XMLHttpRequest, segment: VideoSegment): void;
    /**
     * Canonical XHR exit point. `loadend` fires after every termination path —
     * success, HTTP error, network error, abort, browser timeout — so it is the
     * one place where teardown is guaranteed to run. Android parity
     * (`plugin-android@02c4f055` "cancel timeout deadline on every body-source
     * error path"): without this, a network-level failure that never reaches
     * `readyState=4` (DNS fail, CORS reject, connection refused) leaves the
     * connect/total deadlines armed until they fire and `abort()` an already-
     * dead XHR. `clearAttemptTimers` is idempotent so the double-clear on the
     * normal success path (which also clears at `readyState=4`) is harmless.
     */
    loadEndEM(xhr: XMLHttpRequest, segment: VideoSegment, _e: ProgressEvent): void;
    errorEM(xhr: XMLHttpRequest, segment: VideoSegment, e: ProgressEvent): void;
    getStats(): LoaderStats;
    destroy(): void;
    enable(): void;
    disable(): void;
    getIsEnabled(): boolean;
    getResourceIdentifier(): ResourceIdentifier;
    getP2PManifestRegistry(): P2PManifestRegistry;
    getP2PSegmentIdResolver(): P2PSegmentIdResolver;
    getDiskSegmentStore(): DiskSegmentStore;
    getManifestResolutionStats(): {
        parseCount: number;
        resolveCount: number;
        resolveHits: number;
        resolveMisses: number;
        lookaheadHits: number;
        lastHitFastHits: number;
        lastHitForceHits: number;
        multiPassHits: number;
        subManifestAttachments: number;
        manifestCount: number;
        lookaheadSize: number;
        modelHits: number;
        fallbackCount: number;
    };
    private getByteRangeOffset;
}
