/**
 * Internal types
 */
export declare type UploadType = string;
export declare enum UploadMode {
    Multipart = "Multipart",
    Single = "Single"
}
export interface FileToUpload {
    mimetype: string;
    filename: string;
    size: number;
}
export interface PresignedRequestInfo {
    url: string;
    fields?: Array<{
        key: string;
        value: string;
    }>;
    headers?: {
        key: string;
        value: string;
    }[];
}
export declare type PendingChunkUpload = {
    uploadMode: UploadMode;
    uploadId: string;
    partNumber: number;
    promise: Promise<UploadedChunk>;
    cancel: () => void;
};
export declare type UploadedChunk = {
    uploadId: string;
    etag: string;
    partNumber: number;
};
export declare type UploadProgressCallback = (progress: {
    completedChunksCount: number;
    totalChunksCount: number;
}) => void;
export declare type UploadCompleteCallback = (result: UploadedFile[]) => void;
export declare type OneUploadCompleteCallback = (upload: UploadedFile, originalFile: File) => void;
export declare type UploadErrorCallback = (payload: {
    error: Error;
    erroredUpload: InitiatedUploadWithFile;
}) => void;
export interface MultipartUploadChunk {
    uploadMode: UploadMode.Multipart;
    uploadType: UploadType;
    uploadId: string;
    partNumber: number;
    start: number;
    end: number;
    file: File;
    key: string;
}
export interface SingleFileUploadChunk {
    uploadMode: UploadMode.Single;
    uploadType: UploadType;
    uploadId: string;
    partNumber: number;
    request: PresignedRequestInfo;
    file: File;
    key: string;
}
export declare type UploadChunk = MultipartUploadChunk | SingleFileUploadChunk;
export declare type InitiateOperationConfig = {
    uploadType: UploadType;
    maxConcurrentUploads: number;
    initiate: UploadInitiator;
    getPartRequest?: PartRequestFetcher;
};
export declare type CompleteOperationConfig = {
    uploadType: UploadType;
    complete: UploadCompleter;
};
/**
 * External types
 */
export interface S3Object {
    url: string;
    bucket: string;
    key: string;
    filename: string;
    mimetype: string;
    size: number;
}
export declare type UploadedFile = Omit<S3Object, 'url'> & ({
    uploadMode: UploadMode.Multipart;
    uploadId: string;
    parts: {
        etag: string;
        partNumber: number;
    }[];
} | {
    uploadMode: UploadMode.Single;
    uploadId: string;
});
export declare type InitiatedUpload = {
    uploadMode: UploadMode.Multipart;
    uploadType: UploadType;
    filename: string;
    mimetype: string;
    bucket: string;
    key: string;
    size: number;
    uploadId: string;
    chunkSize: number;
    partsCount: number;
    presignedRequest: null;
} | {
    uploadMode: UploadMode.Single;
    uploadType: UploadType;
    filename: string;
    mimetype: string;
    bucket: string;
    key: string;
    size: number;
    uploadId: string;
    chunkSize: number;
    partsCount: number;
    presignedRequest: PresignedRequestInfo;
};
export declare type InitiatedUploadWithFile = InitiatedUpload & {
    file: File;
};
export declare type CancellableUpload = InitiatedUploadWithFile & {
    cancel: () => void;
};
export declare type PendingUpload = {
    uploadType: UploadType;
    promise: Promise<UploadedFile>;
    upload: CancellableUpload;
    cancel: () => void;
};
export interface PendingUploads {
    promise: Promise<Awaited<PendingUpload['promise']>[]>;
    uploadType: UploadType;
    uploads: CancellableUpload[];
    cancelAll: () => void;
}
export declare type ContextBase<UType extends string | number | symbol> = {
    [type in UType]: {
        initiate: unknown;
        complete: unknown;
    };
};
export declare type UploadInitiator = (files: File[], ctx: any) => Promise<InitiatedUpload[]>;
export declare type UploadCompleter = (files: UploadedFile[], ctx: any) => Promise<S3Object[]>;
export declare type PartRequestFetcher = (upload: MultipartUploadChunk) => Promise<PresignedRequestInfo>;
export declare type Config<UType extends UploadType = UploadType> = {
    maxConcurrentUploads?: number;
    uploads: {
        [uType in UType]: {
            maxConcurrentUploads?: number;
            initiate: UploadInitiator;
            complete?: UploadCompleter;
            getPartRequest?: PartRequestFetcher;
        };
    };
};
export declare type UTypeBase<C extends Config> = keyof C['uploads'] & UploadType;
export declare type UCompleterBase<UType extends UploadType> = {
    [type in UType]: {
        hasComplete: boolean;
    };
};
export declare type Module<UType extends UploadType = UploadType, UCompleter extends UCompleterBase<UType> = UCompleterBase<UType>, Ctx extends ContextBase<UType> = ContextBase<UType>> = {
    [uType in UType]: {
        uploadOne: (file: File, callbacks?: {
            onProgress?: UploadProgressCallback;
            onError?: UploadErrorCallback;
            onComplete?: UploadCompleteCallback;
            onUploadComplete?: OneUploadCompleteCallback;
        }, ...ctx: undefined extends Ctx[uType]['initiate'] ? [Ctx[uType]['initiate']?] : [Ctx[uType]['initiate']]) => Promise<PendingUpload>;
        uploadMany: (files: File[], callbacks?: {
            onProgress?: UploadProgressCallback;
            onError?: UploadErrorCallback;
            onComplete?: UploadCompleteCallback;
            onUploadComplete?: OneUploadCompleteCallback;
        }, ...ctx: undefined extends Ctx[uType]['initiate'] ? [Ctx[uType]['initiate']?] : [Ctx[uType]['initiate']]) => Promise<PendingUploads>;
    } & (UCompleter[uType]['hasComplete'] extends true ? {
        completeOne: (file: UploadedFile, ...ctx: undefined extends Ctx[uType]['complete'] ? [Ctx[uType]['complete']?] : [Ctx[uType]['complete']]) => Promise<S3Object>;
        completeMany: (file: UploadedFile[], ...ctx: undefined extends Ctx[uType]['complete'] ? [Ctx[uType]['complete']?] : [Ctx[uType]['complete']]) => Promise<S3Object[]>;
    } : Record<never, never>);
};
