import { VideoSegment } from '../Storage/VideoSegment';
import Peer from './Peer';
import BalancerOptions from '../Utils/Options';
import SegmentStorage from '../Storage/SegmentStorage';
import Loader from './Loader';
import Cdn from './Cdn';
import DiskSegmentStore from '../Storage/DiskSegmentStore';
import { P2PDerivedTiming } from './P2PDerivedTiming';
import { SwarmAccessDecision } from './SwarmIdentity';
import P2PManifestRegistry from './P2PManifestRegistry';
import { TrackTypeValue } from './P2PSegmentIdResolver';
declare global {
    interface Window {
        P2PManager: any | undefined;
    }
}
/**
 * @type {peer}
 * Peer defined by bittorrent-tracker.
 */
type peer = {
    id: string;
    on: (string: any, callback: any) => null;
    off: (string: any, callback: any) => null;
    write: (string: any) => null;
    destroy: () => null;
};
/**
 * @class
 * @description P2P manager class, that creates the P2P client and manages the peers and request segments to them.
 * @exports P2PLoader
 */
export default class P2PLoader {
    upload: boolean;
    private _isEnabled;
    private _runtimeP2pEnabled;
    private _packageFound;
    private _maxConcurrent;
    private _storage;
    private _accountCode;
    private _options;
    private _maxConnectedPeers;
    private _renditionStableSegmentCount;
    private _activeVideoRendition?;
    private _candidateVideoRendition?;
    private _candidateStableCount;
    private _peerTimeoutsForBan;
    /** V2 disk store (IndexedDB-backed). Populated by Loader at construction. */
    private _diskStore?;
    /** V2 manifest registry (for rendition bandwidth lookups). */
    private _manifestRegistry?;
    /** V2 timing scales received from /decision (all default to 1.0 when absent). */
    private _timingScales;
    /** Backend-configured minimum rendition bandwidth (bps) below which P2P is skipped. 0 = disabled. */
    private _minRenditionBandwidthBps;
    /** Backend-configured minimum CDN throughput (bps) required to announce CDN captures to peers. 0 = disabled. */
    private _minUploadBandwidthBps;
    /** EMA of observed CDN throughput (bps). Feeds the upload gate in `querySwarmAccess`. */
    private _cdnEmaBandwidthBps;
    /** Cached derived timing for the currently active rendition (rebuilt on activateRendition). */
    private _activeDerivedTiming?;
    /**
     * Fallback bandwidth (bps) for the currently active rendition, captured
     * from the `Resource` model at activate time. Used when the manifest
     * registry has no BANDWIDTH entry for the rendition key (e.g. DASH MPDs
     * that omit the bandwidth attribute). 0 means "no info available".
     */
    private _activeRenditionBandwidthBps;
    /**
     * L3: Backend-driven track-type allowlist (from /decision `shareTrackTypes`).
     * Default `['video']` — mirrors the fallback in Android `PeersManager`.
     * Use `normalizeShareTrackTypes` to keep the set canonical.
     */
    private _shareTrackTypes;
    /**
     * L4 / M5: Cache retention in ms. Default 120 s — matches
     * Android `PeersManager.DEFAULT_CACHE_RETENTION_SECONDS = 120` and iOS
     * `P2PLoader.cacheRetentionSeconds = 120`.
     */
    private _cacheRetentionMs;
    /**
     * L4 / M5: Cache max bytes. Default 128 MiB — matches Android
     * `PeersManager.DEFAULT_CACHE_MAX_BYTES` and iOS `P2PLoader.cacheMaxBytes`.
     */
    private _cacheMaxBytes;
    /** L4: Interval handle for the periodic eviction timer. */
    private _cacheEvictionTimer?;
    /** Signature of the static P2P options used to build the current P2PManager. */
    private _staticOptionsSignature?;
    /** Peers managing */
    private _p2pManager?;
    private _peers;
    private _bannedPeers;
    private _candidates;
    private _activeDownloads;
    private _segmentsRequested;
    private _activeDownloadIds;
    private _monitoringStarted;
    private _performReset;
    /** Per-segment local claim role selected by leader election (PRIMARY/BACKUP). */
    private _localClaimRoles;
    /** Statistic params */
    private _downloadedPeers;
    private _uplodadedPeers;
    private _maxBandwidth;
    private _minBandwidth;
    private _timeoutDiscardedBytes;
    private _failedRequests;
    private _timeoutRequests;
    private _segmentAbsentRequests;
    private _errorRequests;
    private _downloadMillis;
    private _byteDownloadCount;
    private _chunkDownloadCount;
    private _sumResponseBytes?;
    private _minResponseBytes?;
    private _maxResponseBytes?;
    private _samplesResponseBytes?;
    private _sumResponseTime?;
    private _minResponseTime?;
    private _maxResponseTime?;
    private _samplesResponseTime?;
    private _sumNetworkLatency?;
    private _minNetworkLatency?;
    private _maxNetworkLatency?;
    private _samplesNetworkLatency?;
    private _sumThroughput?;
    private _minThroughput?;
    private _maxThroughput?;
    private _samplesThroughput?;
    private _sumVideoBytes?;
    private _sumVideoTime?;
    private _totalPeerSet;
    private _activePeerSet;
    private _availablePeersMap;
    private _peersAvailable?;
    private _maxPeersAvailable?;
    private _minPeersAvailable?;
    private _peersUsed?;
    private _peersParallelUsed?;
    private _maxPeersParallelUsed?;
    private _minPeersParallelUsed?;
    private _peerDiscoveryTime?;
    private _peerConnectionTime?;
    private _sessionMaxActivePeers;
    private _updatePeersMetricsRefCounter;
    private _offerInterval;
    private _switches;
    private _switchesDueToQuality;
    private _switchesDueToConnectivity;
    private _switchesDueToErrors;
    private _accumBw;
    private _downloadMillisVideo;
    private _downloadedBytesVideo;
    private _downloadedChunksVideo;
    private _byteUploadDiscardedCount;
    private _chunkUploadDiscardedCount;
    private _chunkUploadCount;
    private _byteUploadCount;
    private _uploadRequests;
    private _uploadRequestsFailed;
    private _destroyed;
    private _cdnObject;
    private _cdnPingTimeBean;
    /**
     * Constructs P2PLoader.
     * @param accountCode
     * @param {BalancerOptions} options Options object.
     * @param {SegmentStorage} storage SegmentStore object.
     */
    constructor(accountCode: string, options: BalancerOptions, storage: SegmentStorage);
    isEnabled(): boolean;
    enable(): void;
    disable(): void;
    getStorage(): SegmentStorage;
    getUploadedUniqPeers(): number;
    getPeersAhead(): number;
    getPeersBehind(): number;
    getPeersNothing(): number;
    getId(): any;
    getCdnObject(): Cdn;
    resetP2PConnection(): void;
    /**
     * Input for `info_hash` (content-level, NO rendition). Byte-for-byte parity
     * with Android `StringUtil.generateInfoHash(accountCode, mediaUrl, videoId, swarmIdentity)`:
     *   1. videoId  (highest priority)  -> `accountCode + videoId`
     *   2. swarmIdentity canonicalId    -> `accountCode + canonicalId`
     *   3. manifest URL path            -> `accountCode + getUrlPath(resource)`
     * Hashed by P2PManager via `Util.hash` (SHA-256, first 32 hex chars).
     */
    private _buildInfoHashInput;
    /**
     * Input for `npaw-peer-group` (swarm-level, WITH rendition). Matches Android
     * `P2pManager.computeSwarmId`: `accountCode + manifestUrl + rendition` concatenated directly.
     * Returns undefined when either resource or active rendition is missing, so no
     * query param is attached to the WebSocket handshake.
     */
    private _buildSwarmIdInput;
    private _buildTrackerResource;
    private _buildRenditionKey;
    private _clearRenditionCandidate;
    private _observeSegmentRendition;
    private _clearPeerState;
    /**
     * L2: Pushes the canonical SwarmIdentity resolved by the registry into the
     * P2PManager so the Join payload includes `canonical_swarm_id` +
     * `canonical_swarm_source` (parity with Android `sendJoin`). No-op when
     * the registry has not yet resolved one.
     */
    private _applyCanonicalSwarmIdentityToManager;
    private _switchSwarm;
    private _shutdownP2PManager;
    sendJoin(): void;
    /**
     * Sets P2P settings from API response.
     * @param {balancerResponse} e API response.
     * @public
     */
    setSettings(e: balancerResponse): void;
    setRuntimeP2pEnabled(enabled: boolean): void;
    startMonitoring(): void;
    isMaxPeers(): boolean;
    getMissingPeers(): number;
    getMaxPeers(): number;
    getBannedPeers(): Map<string, boolean>;
    getUploadRequests(): number;
    getUploadRequestsFailed(): number;
    /**
     * @param {string} id Id of the segment.
     * @returns {VideoSegment|undefined} Segment object corresponding to the id, or undefined.
     * @public
     */
    getSegment(segment: VideoSegment): VideoSegment | undefined;
    /**
     * Return the list of peers that can serve the video segment
     *
     * @param segment Video segment object to be requested.
     */
    getPeersWithContent(segment: VideoSegment): Peer[];
    /**
     * Tries to check if the segment is available from any peer, and returns if it is or not.
     * @param {VideoSegment} seg Video segment object to be requested.
     * @returns {boolean} If the segment can be downloaded using P2P or not.
     * @public
     */
    request(segment: VideoSegment, loader?: Loader): boolean;
    addPeerResponse(response: responseStorageObject): void;
    private getLastResponses;
    addPeerLatency(peerLatency: number): void;
    /**
     * Callback for error event from P2P Client.
     * @param {Object} e Error event data.
     * @private
     * @static
     */
    private static _errorListener;
    /**
     * Callback for warning event from P2P Client.
     * @param {Object} e Warning event data.
     * @private
     * @static
     */
    private static _warningListener;
    /**
     * If p2p upload enabled, it stores the downloaded segment to share it with peers.
     * @param segment Segment to store.
     * @param data Data to store in the segment in memory.
     * @public
     */
    storeSegment(segment: VideoSegment): void;
    /**
     * Method to be called when we want to notify the peers that we have an updated map (list of video segments).
     * @private
     */
    private _sendMapToAllPeersV0;
    /**
     * Method to be called when we want to notify the peers I have a new segment available.
     * @private
     */
    private _sendNewSegmentToAllPeersV1;
    /**
     * Method to be called when we want to notify the peers that we have an updated map (list of video segments).
     * @private
     */
    private _sendMapToPeer;
    /**
     * Callback for new peer candidate event from P2P Client.
     * @param {callbackData} e Peer information to listen.
     * @private
     */
    addPeerCandidate(peer: peer, answer: any): void;
    /**
     * If the peer is connected and didnt exist adds it to peers list and removes the candidates.
     * If it existed before and was connected, it deletes it.
     * @param {Object} e Event object with event name and the new peer.
     * @private
     */
    peerConnect(peer: Peer): void;
    /**
     * Callback of close peer event. Will remove it from candidates and peers.
     * @param {Object} e Event object with event name and the peer to remove.
     * @private
     */
    peerCloseListener(data: Peer): void;
    /**
     * Callback of peer segment request event. Given a request if available it returns the chosen segment.
     * @param {Object} e Callback data from peer segment request event.
     * @private
     */
    peerSegmentUploadRequest(peer: Peer, segmentId: string, operationId: number): void;
    /**
     * Callback from peer segment loaded. It gets the data and adds it to the segment object,
     * then triggers the success event of it.
     * @param {Object} e Callback data from peer segment loaded event.
     * @private
     */
    peerSegmentLoaded(peer: Peer, id: string, time: number, data: ArrayBuffer): void;
    /**
     * Callback from peer segment loading progress. It gets the data and adds it to the segment object,
     * then triggers the success event of it.
     * @param {Object} e Callback data from peer segment loaded event.
     * @private
     */
    peerSegmentProgress(peer: Peer, id: string, time: number, data: ArrayBuffer, size: number): void;
    peerFailedSegmentTimeout(peer: Peer, id: string, size: number): void;
    peerFailedSegmentAbsent(peer: Peer, id: string): void;
    private _checkAndBanPeer;
    /**
     * Callback from peer segment uploaded. Counts the downloaded bytes and segments.
     * @param {Object} e callback data from peer segment uploaded event.
     * @private
     */
    peerSegmentUpload(size: number): void;
    getUploadedBytes(): number;
    getUploadedChunks(): number;
    /**
     * Callback from peer segment request cancelled. Counts the uploaded bytes that wont be used by the peer.
     * @param {Object} e callback data from peer segment upload failed event.
     * @private
     */
    peerCanceledSegmentUpload(size: number): void;
    /**
     * Destroys the client and the peers/candidates.
     * To be called when view is over or content switched.
     * @public
     */
    destroy(): void;
    /**
     * Returns the timestamp of the oldest request stored from all the peers.
     * @returns {number} Timestamp of the oldest request stored.
     * @public
     */
    getOldestRequestTS(): number;
    getPeers(): Map<string, Peer>;
    /**
     * Returns an object with the P2P data stats of the current content/view.
     * @returns {P2PLoaderStats} P2P info object.
     * @public
     */
    getStats(): P2PLoaderStats;
    /**
     * Android P2pProvider parity (lastFailureReason + switch tracking). Called
     * whenever a segment that was originally routed via P2P ends up being
     * served by a CDN instead — either via the V2 Loader._fallBackP2pToCdn
     * paths (cache miss, access denied, election timeout, dispatch crash),
     * via the Loader.onProcessSegmentFail re-route, or via the V1 send-handler
     * timeout fallback in CdnBalancer. The counter flows into the /cdn ping
     * P2P entry as `switches` + `switches_due_*`.
     */
    recordSwitchFromP2P(reason: 'quality' | 'connectivity' | 'errors'): void;
    resetOnPing(): void;
    onOffer(peerId: string, offerInterval: number): void;
    updatePeerMetrics(): void;
    onConnected(peerConnectionTime: number): void;
    onDiscovery(discoveryTime: number): void;
    /** Called by Loader right after construction to wire the shared V2 collaborators. */
    attachV2Collaborators(store: DiskSegmentStore, registry: P2PManifestRegistry): void;
    getActiveVideoRendition(): string | undefined;
    /**
     * Whether P2P access is allowed for the current swarm AND whether we should
     * announce CDN captures to peers. Used by the CDN capture path to decide
     * between "download & share" vs "download & keep to ourselves".
     *
     * G1 enforcement:
     *   - `p2pMinRenditionBandwidthBps`: denies peer access entirely when the
     *     active rendition's declared bandwidth is below the threshold.
     *   - `p2pMinUploadBandwidthBps`: flips `announceCapture` off when our CDN
     *     throughput EMA indicates we can't comfortably re-upload segments.
     */
    /**
     * L1: Per-rendition swarm access. Takes the segment's `v2Rendition` /
     * `v2TrackType` from the VideoSegment's resolver-populated fields (or an
     * explicit resolved snapshot) and applies the iOS/Android gate:
     *   - video segment AND rendition == activeVideoRendition -> allowed
     *   - video segment AND rendition != activeVideoRendition -> denied
     *   - non-video track                                      -> allowed
     *   - no active rendition yet                              -> denied
     *
     * The bandwidth gates stay as before. `announceCapture` requires
     * `upload=true`, adequate CDN EMA and, for video, the matching rendition.
     */
    querySwarmAccess(resolved?: {
        trackType: TrackTypeValue;
        rendition?: string;
    }): SwarmAccessDecision;
    /**
     * Side-effectful wrapper around `querySwarmAccess` used on the CDN capture
     * path. Mirrors iOS `observeResolvedSegment`. Invoked per media segment
     * completion so we also get a chance to re-evaluate the active rendition.
     */
    observeResolvedSegment(segment: VideoSegment): SwarmAccessDecision;
    /**
     * Records a CDN throughput sample (bps) into the EMA used by the upload gate.
     * Alpha mirrors the EMA used for per-peer transfer speed (0.3).
     */
    recordCdnThroughput(bitsPerSecond: number): void;
    getCdnEmaBandwidthBps(): number;
    /**
     * Builds derived timing for a given segment duration using the current
     * TimingScaleConfig. Mirrors iOS/Android `P2PDerivedTiming.fromSegmentDuration`.
     */
    getDerivedTimingForSegment(segmentDurationMs?: number): P2PDerivedTiming;
    /**
     * H1: Early-announcement path — creates the ACQUIRING entry in the disk store
     * at CDN-capture start and notifies peers with SEGMENT_STATE(ACQUIRING, PRIMARY)
     * + a lease derived from the current timing config. Followers can then stream
     * the in-flight segment via GrowingSegmentReader while we're still downloading
     * from the CDN. Mirrors iOS `storeAndAnnounceSegment` (commit 5ae40fa).
     */
    announceAcquiringSegment(segment: VideoSegment, access: SwarmAccessDecision): void;
    /** Per-segment counter of bytes already appended to the disk store during ACQUIRING. */
    private _acquiringAppendedBytes;
    /**
     * Progressive append for an ACQUIRING segment. The caller passes the full
     * response buffer so far (XHR gives us cumulative bytes on each progress
     * tick); we extract the unseen suffix and push it into the disk store so
     * any open GrowingSegmentReader wakes up and streams the new bytes.
     */
    appendAcquiringBytes(segment: VideoSegment, cumulative: ArrayBuffer | undefined): void;
    /**
     * F3: CDN-captured segment goes through the V2 disk store, flipping its
     * state machine ACQUIRING -> READY and notifying peers via SEGMENT_STATE.
     * Idempotent (safe to call multiple times for the same segment).
     */
    storeSegmentV2(segment: VideoSegment, access: SwarmAccessDecision): void;
    /**
     * H2: V2-style request path. Runs the leader-election poll first; if a peer
     * is found advertising ACQUIRING or READY for this segment within the
     * election window, issues the peer request and returns true. Otherwise
     * returns false so the caller can fall back to CDN. Non-destructive wrt the
     * legacy synchronous `request()` — callers that want election opt in here.
     */
    requestAsyncWithElection(segment: VideoSegment): Promise<boolean>;
    /**
     * K2: Track-type filter. Defaults to accepting only video tracks to match
     * the `shareTrackTypes=['video']` default used by iOS/Android — audio and
     * subtitle segments are small enough that the P2P overhead isn't worth it.
     * Exposed as public so callers can gate symmetrical decisions (e.g. the
     * upload path in `storeSegmentV2`).
     */
    canShareTrack(trackType: TrackTypeValue | undefined): boolean;
    /**
     * Java `String.hashCode()` implementation used for deterministic peer-id
     * selection. Signed 32-bit, exactly the algorithm iOS/Android use on the
     * same inputs so all three platforms compute the same winner.
     */
    private static _javaStringHashCode;
    /**
     * Deterministic per-segment delay used to decide claim priority. Lower
     * derived value => higher priority. Matches iOS `deterministicClaimDelay`:
     * `hashCode(segmentId + ':' + localPeerId)` normalized into [0, electionWindowMs].
     */
    determineLocalClaimRole(segmentId: string, electionWindowMs: number): number;
    /**
     * Polls the peer set for up to `electionWindowMs` (10 ticks of 50ms by
     * default) looking for a peer that has the segment available (READY or
     * ACQUIRING with a live lease). Returns the first eligible peer found, or
     * undefined if the window elapses with no candidate — in which case the
     * caller should treat itself as the leader and go to CDN.
     */
    awaitLeaderOrPeer(segmentId: string, electionWindowMs: number): Promise<Peer | undefined>;
    private _determineLocalClaimRoleForSegment;
    /**
     * Recomputes the active rendition side-effects: refreshes the derived-timing
     * snapshot under the current `TimingScaleConfig`. Called whenever the
     * rendition stability threshold triggers a swarm switch.
     */
    private _refreshDerivedTiming;
    /**
     * L4: Starts/restarts the periodic disk-cache eviction timer. Matches
     * Android `PeersManager.handleSegmentRetention`: every 30 seconds, evict
     * READY segments older than `cacheRetentionMs` and, if the total still
     * exceeds `cacheMaxBytes`, drop the LRU tail. Runs only while P2P is
     * enabled; `_shutdownP2PManager`/`disable` stop it.
     */
    private _startCacheEvictionTimer;
    private _stopCacheEvictionTimer;
    /**
     * K1: Derived first-byte timeout for a peer request. Prefers the active
     * rendition's snapshot (cached at activate time) and falls back to a
     * per-segment computation using the segment's declared duration. Matches
     * the `timingForResolvedSegment` helper used by Android `P2pProvider`.
     */
    private _resolveFirstByteTimeout;
    /**
     * H3 + K4: serve an ACQUIRING segment to a peer by waiting for it to
     * transition to READY and then forwarding the finalized payload.
     *
     * Waiters fire on any mutation (each `append` included), not just state
     * transitions. We loop — re-subscribing after each intermediate notify —
     * until either the state becomes terminal or the active rendition's
     * `fallbackBudgetMs` budget elapses. Parity with the
     * `GrowingSegmentReader.readNextChunk` wait semantics.
     */
    private _streamAcquiringToPeer;
}
export {};
