declare type AcceptedEvents = string | WorkerEvents | DownloaderEvents | DownloaderStates;

declare interface BaseFile {
    completed: boolean;
    id: string;
    kind: FileKinds;
    last_modified: string;
    name: string;
    path: string;
    size: number;
    virus_detected: boolean;
}

export declare interface Chunk {
    index: number;
    start: number;
    end: number;
    progress: number;
}

declare interface ChunkedFile {
    fileId: string;
    index: number;
    file: DownloadFile;
    chunkSize: number;
}

export declare class Downloader extends EventEmitter {
    private readonly linkPassword;
    private readonly chunkSize;
    private fdownloader;
    private readonly linkID;
    private readonly linkSecret;
    private packageID;
    private packageToken;
    private packageName;
    private packageSize;
    private directoryHandle;
    private fileQueue;
    private fileCount;
    private progressTracker;
    private filesFinished;
    private currentFileIndex;
    private currentFetchedFileIndex;
    private fileMap;
    private pendingLinkQueue;
    private finishedFiles;
    private requestingLinks;
    private apiClient;
    private erroredFiles;
    private parentDirectoryName;
    private fileConcurrency;
    private chunkConcurrency;
    status: DownloaderStates;
    downloadState: DownloadState;
    static readonly DownloaderEvents: typeof DownloaderEvents;
    static readonly Emit = "emit";
    static readonly States: typeof DownloaderStates;
    downloadCompleted: boolean;
    constructor(masvLink: string, linkPassword?: string, apiBaseUrl?: string, chunkSize?: number, masvUserAgent?: string);
    initialize(): Promise<void>;
    private changeStatus;
    private onCreateParentDirectory;
    private onDownloadCancelled;
    private onFileFinish;
    private onChunkFinish;
    private onFileProgress;
    private onDownloadError;
    private onDownloadRetry;
    private onDownloadAbort;
    private onDownloadLinkExpired;
    private get canDownloadFile();
    private get allDownloadLinksFetched();
    private isLowFileDensity;
    private isHighFileDensity;
    private getFileConcurrency;
    private getChunkConcurrency;
    private fetchMetaDataLinks;
    private chunkFile;
    private processQueue;
    private queueEmptyFilesAndDirectories;
    private fetchDownloadLinks;
    private fillFileQueue;
    private prepareDownload;
    private getPackageInfo;
    pause(): void;
    cancel(deleteFiles?: boolean): void;
    stop(): void;
    terminate(): void;
    loadFiles(): Promise<BaseFile[]>;
    retry(): Promise<void>;
    start(directoryHandle: FileSystemDirectoryHandle, fileList?: BaseFile[]): Promise<void>;
    private startDownload;
    get totalSize(): number;
    get performanceStats(): PerformanceResults;
    get progressSummary(): ProgressSummary;
}

declare enum DownloaderEvents {
    Start = "download:start",
    Progress = "download:progress",
    Chunk = "download:chunk",
    File = "download:file",
    Error = "download:error",
    Finished = "download:finish",
    FileQueued = "download:file_queued",
    FileDownloaded = "download:file_downloaded",
    Abort = "download:abort",
    Retry = "download:retry",
    PartialFinished = "download:partial_finish",
    FileErrored = "download:file_errored"
}

export declare enum DownloaderStates {
    Idle = "idle",
    Downloading = "downloading",
    Ready = "ready",
    Paused = "paused",
    Finished = "finished",
    PartialFinished = "partial-finished",
    Errored = "errored",
    Terminated = "terminated",
    Cancelled = "cancelled"
}

declare interface DownloadFile extends BaseFile {
    url?: string;
}

declare class DownloadState {
    queue: Record<string, FileState>;
    getFile(fileId: string): FileState | undefined;
    addFile(file: ChunkedFile): FileState;
    removeFile(fileId: string): void;
    setProgress(fileId: string, chunkIndex: number, amount: number): void;
    get length(): number;
}

declare class EventEmitter {
    handlers: HandlerRecord;
    on(name: AcceptedEvents, callback: (payload: EventPayload) => void): void;
    off(name: AcceptedEvents, callback?: (payload: EventPayload) => void): void;
    clearHandlers(): void;
    emit(name: AcceptedEvents, payload?: EventPayload): void;
    bubbleEmit(payload: EventPayload): void;
}

declare interface EventPayload {
    data: unknown;
    event: AcceptedEvents;
    target?: object;
    time?: number;
}

declare enum FileKinds {
    File = "file",
    Directory = "directory",
    Metadata = "metadata",
    ZipMac = "zip_mac",
    ZipWindows = "zip_windows"
}

export declare type FileMap = Record<string, BaseFile>;

declare class FileState {
    id: string;
    index: number;
    file: DownloadFile;
    chunkProgress: Record<number, number>;
    finishedChunks: Set<number>;
    chunkSize: number;
    constructor({ fileId, index, file, chunkSize }: ChunkedFile);
    get totalProgress(): number;
    getChunkProgress(index: number): number | undefined;
    clearChunkProgress(index: number): void;
    writeChunk(index: number): void;
    addChunkProgress(chunkIndex: number, progress: number): void;
}

declare type HandlerRecord = Record<AcceptedEvents, ((payload: EventPayload) => void)[]>;

declare interface PerformanceResults {
    duration: number;
    speed: number;
    instant: number;
    moving: number;
    total: number;
    progress: number;
    chunkProgress: number;
    fileProgress: number;
    totalFiles: number;
    finalizedFiles: number;
}

export declare interface ProgressSummary {
    finalizedBytes: string;
    finalizedFiles: string;
    totalBytes: string;
    totalFiles: string;
    erroredFiles: string;
}

export declare class TerminatedError extends Error {
    constructor();
}

declare enum WorkerEvents {
    Created = "worker:create",
    Cancelled = "worker:cancelled",
    Execute = "worker:execute",
    Finish = "worker:finish",
    FinishFile = "worker:finish-file",
    FinishChunk = "worker:finish-chunk",
    LinkExpired = "worker:link-expired",
    Error = "worker:error",
    Retry = "worker:retry",
    Progress = "worker:progress",
    Terminate = "worker:terminate",
    Abort = "worker:abort",
    CreateParentDirectory = "worker:create-parent-directory"
}

export { }
