import { AxiosResponse } from 'axios';
import { ComponentOptionsMixin } from 'vue';
import { default as default_2 } from 'p-cancelable';
import { DefineComponent } from 'vue';
import { Entry } from '@nextcloud/files';
import { ExtractPropTypes } from 'vue';
import { Folder } from '@nextcloud/files';
import { Node as Node_2 } from '@nextcloud/files';
import { PropType } from 'vue';
import { TypedEventTarget } from 'typescript-event-target';

export declare interface ConflictPickerOptions {
    /**
     * When this is set to true a hint is shown that conflicts in directories are handles recursively
     * You still need to call this function for each directory separately.
     */
    recursive?: boolean;
}

export declare type ConflictResolutionResult<T extends File | FileSystemEntry | Node_2> = {
    selected: T[];
    renamed: T[];
};

/**
 * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */
/**
 * Helpers to generate a file tree when the File and Directory API is used (e.g. Drag and Drop or <input type="file" webkitdirectory>)
 */
/**
 * This is a helper class to allow building a file tree for uploading
 * It allows to create virtual directories
 */
export declare class Directory extends File {
    private _originalName;
    private _path;
    private _children;
    constructor(path: string);
    get size(): number;
    get lastModified(): number;
    get originalName(): string;
    get children(): Array<File | Directory>;
    get webkitRelativePath(): string;
    getChild(name: string): File | Directory | null;
    /**
     * Add multiple children at once
     * @param files The files to add
     */
    addChildren(files: Array<File | FileSystemEntry>): Promise<void>;
    /**
     * Add a child to the directory.
     * If it is a nested child the parents will be created if not already exist.
     * @param file The child to add
     */
    addChild(file: File | FileSystemEntry): Promise<void>;
}

export declare class Eta extends TypedEventTarget<EtaEventsMap> {
    /** Bytes done */
    private _done;
    /** Total bytes to do */
    private _total;
    /** Current progress (cached) as interval [0,1] */
    private _progress;
    /** Status of the ETA */
    private _status;
    /** Time of the last update */
    private _startTime;
    /** Total elapsed time for current ETA */
    private _elapsedTime;
    /** Current speed in bytes per second */
    private _speed;
    /** Expected duration to finish in seconds */
    private _eta;
    /**
     * Cutoff time for the low pass filter of the ETA.
     * A higher value will consider more history information for calculation,
     * and thus suppress spikes of the speed,
     * but will make the overall resposiveness slower.
     */
    private _cutoffTime;
    constructor(options?: EtaOptions);
    /**
     * Add more transferred bytes.
     * @param done Additional bytes done.
     */
    add(done: number): void;
    /**
     * Update the transmission state.
     *
     * @param done The new value of transferred bytes.
     * @param total Optionally also update the total bytes we expect.
     */
    update(done: number, total?: number): void;
    reset(): void;
    /**
     * Pause the ETA calculation.
     */
    pause(): void;
    /**
     * Resume the ETA calculation.
     */
    resume(): void;
    /**
     * Status of the Eta (paused, active, idle).
     */
    get status(): EtaStatus;
    /**
     * Progress (percent done)
     */
    get progress(): number;
    /**
     * Estimated time in seconds.
     */
    get time(): number;
    /**
     * Human readable version of the estimated time.
     */
    get timeReadable(): string;
    /**
     * Transfer speed in bytes per second.
     * Returns `-1` if not yet estimated.
     */
    get speed(): number;
    /**
     * Get the speed in human readable format using file sizes like 10KB/s.
     * Returns the empty string if not yet estimated.
     */
    get speedReadable(): string;
}

export declare interface EtaEventsMap {
    pause: CustomEvent;
    reset: CustomEvent;
    resume: CustomEvent;
    update: CustomEvent;
}

declare interface EtaOptions {
    /** Low pass filter cutoff time for smoothing the speed */
    cutoffTime?: number;
    /** Total number of bytes to be expected */
    total?: number;
    /** Start the estimation directly */
    start?: boolean;
}

export declare enum EtaStatus {
    Idle = 0,
    Paused = 1,
    Running = 2
}

/**
 * Get the conflicts between two sets of files
 * @param {Array<File|FileSystemEntry|Node>} files the incoming files
 * @param {Node[]} content all the existing files in the directory
 * @return {boolean} true if there is a conflict
 */
export declare function getConflicts<T extends File | FileSystemEntry | Node_2>(files: T[], content: Node_2[]): T[];

/**
 * Get the global Uploader instance.
 *
 * Note: If you need a local uploader you can just create a new instance,
 * this global instance will be shared with other apps.
 *
 * @param isPublic Set to true to use public upload endpoint (by default it is auto detected)
 * @param forceRecreate Force a new uploader instance - main purpose is for testing
 */
export declare function getUploader(isPublic?: boolean, forceRecreate?: boolean): Uploader;

/**
 * Check if there is a conflict between two sets of files
 * @param {Array<File|FileSystemEntry|Node>} files the incoming files
 * @param {Node[]} content all the existing files in the directory
 * @return {boolean} true if there is a conflict
 */
export declare function hasConflict(files: (File | FileSystemEntry | Node_2)[], content: Node_2[]): boolean;

/**
 * Interface of the internal Directory class
 */
export declare type IDirectory = Pick<Directory, keyof Directory>;

/**
 * Open the conflict resolver
 * @param {string} dirname the directory name
 * @param {(File|Node)[]} conflicts the incoming files
 * @param {Node[]} content all the existing files in the directory
 * @param {ConflictPickerOptions} options Optional settings for the conflict picker
 * @return {Promise<ConflictResolutionResult>} the selected and renamed files
 */
export declare function openConflictPicker<T extends File | FileSystemEntry | Node_2>(dirname: string | undefined, conflicts: T[], content: Node_2[], options?: ConflictPickerOptions): Promise<ConflictResolutionResult<T>>;

export declare class Upload {
    private _source;
    private _file;
    private _isChunked;
    private _chunks;
    private _size;
    private _uploaded;
    private _startTime;
    private _status;
    private _controller;
    private _response;
    constructor(source: string, chunked: boolean | undefined, size: number, file: File);
    get source(): string;
    get file(): File;
    get isChunked(): boolean;
    get chunks(): number;
    get size(): number;
    get startTime(): number;
    set response(response: AxiosResponse | null);
    get response(): AxiosResponse | null;
    get uploaded(): number;
    /**
     * Update the uploaded bytes of this upload
     */
    set uploaded(length: number);
    get status(): number;
    /**
     * Update this upload status
     */
    set status(status: UploadStatus);
    /**
     * Returns the axios cancel token source
     */
    get signal(): AbortSignal;
    /**
     * Cancel any ongoing requests linked to this upload
     */
    cancel(): void;
}

/**
 * Upload a file
 * This will init an Uploader instance if none exists.
 * You will be able to retrieve it with `getUploader`
 *
 * @param {string} destinationPath the destination path
 * @param {File} file the file to upload
 * @return {Uploader} the uploader instance
 */
export declare function upload(destinationPath: string, file: File): Uploader;

/**
 * Helper function to create a conflict resolution callback for the `Uploader.batchUpload` method.
 *
 * This creates a callback that will open the conflict picker to resolve the conflicts.
 * In case of a rename the new name is validated and the invalid filename dialog is shown an error happens there.
 *
 * @param contentsCallback Callback to retrieve contents of a given path
 */
export declare function uploadConflictHandler(contentsCallback: (path: string) => Promise<Node_2[]>): (nodes: Array<File | IDirectory>, path: string) => Promise<Array<File | IDirectory> | false>;

export declare class Uploader {
    private _destinationFolder;
    private _isPublic;
    private _customHeaders;
    private _uploadQueue;
    private _jobQueue;
    private _queueSize;
    private _queueProgress;
    private _queueStatus;
    private _eta;
    private _notifiers;
    /**
     * Initialize uploader
     *
     * @param {boolean} isPublic are we in public mode ?
     * @param {Folder} destinationFolder the context folder to operate, relative to the root folder
     */
    constructor(isPublic?: boolean, destinationFolder?: Folder);
    /**
     * Get the upload destination path relative to the root folder
     */
    get destination(): Folder;
    /**
     * Set the upload destination path relative to the root folder
     */
    set destination(folder: Folder);
    /**
     * Get the root folder
     */
    get root(): string;
    /**
     * Get registered custom headers for uploads
     */
    get customHeaders(): Record<string, string>;
    /**
     * Set a custom header
     * @param name The header to set
     * @param value The string value
     */
    setCustomHeader(name: string, value?: string): void;
    /**
     * Unset a custom header
     * @param name The header to unset
     */
    deleteCustomerHeader(name: string): void;
    /**
     * Get the upload queue
     */
    get queue(): Upload[];
    private reset;
    /**
     * Pause any ongoing upload(s)
     */
    pause(): void;
    /**
     * Resume any pending upload(s)
     */
    start(): void;
    /**
     * Get the estimation for the uploading time.
     */
    get eta(): Eta;
    /**
     * Get the upload queue stats
     */
    get info(): {
        size: number;
        progress: number;
        status: UploaderStatus;
    };
    private updateStats;
    addNotifier(notifier: (upload: Upload) => void): void;
    /**
     * Notify listeners of the upload completion
     * @param upload The upload that finished
     */
    private _notifyAll;
    /**
     * Uploads multiple files or folders while preserving the relative path (if available)
     * @param {string} destination The destination path relative to the root folder. e.g. /foo/bar (a file "a.txt" will be uploaded then to "/foo/bar/a.txt")
     * @param {Array<File|FileSystemEntry>} files The files and/or folders to upload
     * @param {Function} callback Callback that receives the nodes in the current folder and the current path to allow resolving conflicts, all nodes that are returned will be uploaded (if a folder does not exist it will be created)
     * @return Cancelable promise that resolves to an array of uploads
     *
     * @example
     * ```ts
     * // For example this is from handling the onchange event of an input[type=file]
     * async handleFiles(files: File[]) {
     *   this.uploads = await this.uploader.batchUpload('uploads', files, this.handleConflicts)
     * }
     *
     * async handleConflicts(nodes: File[], currentPath: string) {
     *   const conflicts = getConflicts(nodes, this.fetchContent(currentPath))
     *   if (conflicts.length === 0) {
     *     // No conflicts so upload all
     *     return nodes
     *   } else {
     *     // Open the conflict picker to resolve conflicts
     *     try {
     *       const { selected, renamed } = await openConflictPicker(currentPath, conflicts, this.fetchContent(currentPath), { recursive: true })
     *       return [...selected, ...renamed]
     *     } catch (e) {
     *       return false
     *     }
     *   }
     * }
     * ```
     */
    batchUpload(destination: string, files: (File | FileSystemEntry)[], callback?: (nodes: Array<File | IDirectory>, currentPath: string) => Promise<Array<File | IDirectory> | false>): default_2<Upload[]>;
    /**
     * Helper to create a directory wrapped inside an Upload class
     * @param destination Destination where to create the directory
     * @param directory The directory to create
     * @param client The cached WebDAV client
     */
    private createDirectory;
    private uploadDirectory;
    /**
     * Upload a file to the given path
     * @param {string} destination the destination path relative to the root folder. e.g. /foo/bar.txt
     * @param {File|FileSystemFileEntry} fileHandle the file to upload
     * @param {string} root the root folder to upload to
     * @param retries number of retries
     */
    upload(destination: string, fileHandle: File | FileSystemFileEntry, root?: string, retries?: number): default_2<Upload>;
    /**
     * Create modification time headers if valid value is available.
     * It can be invalid on Android devices if SD cards with NTFS / FAT are used,
     * as those files might use the NT epoch for time so the value will be negative.
     *
     * @param file The file to upload
     */
    private _mtimeHeader;
}

export declare enum UploaderStatus {
    IDLE = 0,
    UPLOADING = 1,
    PAUSED = 2
}

export declare const UploadPicker: DefineComponent<    {
accept: {
type: PropType<string[]>;
default: null;
};
disabled: {
type: BooleanConstructor;
default: boolean;
};
multiple: {
type: BooleanConstructor;
default: boolean;
};
/**
* Allow to disable the "new"-menu for this UploadPicker instance
*/
noMenu: {
type: BooleanConstructor;
default: boolean;
};
/**
* Allow to disable the button label
*/
noLabel: {
type: BooleanConstructor;
default: boolean;
};
/**
* Make the "New"-button primary color.
*/
primary: {
type: BooleanConstructor;
default: boolean;
};
destination: {
type: typeof Folder;
default: undefined;
};
allowFolders: {
type: BooleanConstructor;
default: boolean;
};
/**
* List of file present in the destination folder
* It is also possible to provide a function that takes a relative path to the current directory and returns the content of it
* Note: If a function is passed it should return the current base directory when no path or an empty is passed
*/
content: {
type: PropType<Node_2[] | ((relativePath?: string) => Node_2[] | PromiseLike<Node_2[]>)>;
default: () => never[];
};
/**
* Overwrite forbidden characters (by default the capabilities of the server are used)
* @deprecated Deprecated and will be removed in the next major version
*/
forbiddenCharacters: {
type: PropType<string[]>;
default: () => never[];
};
}, {
t: (original: string, placeholders?: Record<string, string | number>) => string;
progressTimeId: string;
}, {
newFileMenuEntries: Entry[];
openedMenu: boolean;
uploadManager: Uploader;
}, {
menuEntriesUpload(): Entry[];
menuEntriesNew(): Entry[];
menuEntriesOther(): Entry[];
/**
* Check whether the current browser supports uploading directories
* Hint: This does not check if the current connection supports this, as some browsers require a secure context!
*/
canUploadFolders(): boolean;
queue(): Upload[];
hasFailure(): boolean;
isAssembling(): boolean;
isUploading(): boolean;
isOnlyAssembling(): boolean;
isPaused(): boolean;
buttonLabel(): string;
haveMenu(): boolean;
}, {
etaTimeAndSpeed(): string;
/**
* Handle clicking a new-menu entry
* @param entry The entry that was clicked
*/
onClick(entry: Entry): Promise<void>;
/**
* Trigger file picker
* @param uploadFolders Upload folders
*/
onTriggerPick(uploadFolders?: boolean): void;
/**
* Helper for backwards compatibility that queries the content of the current directory
* @param path The current path
*/
getContent(path?: string): Promise<Node_2[]>;
/**
* Start uploading
*/
onPick(): Promise<void>;
resetForm(): void;
/**
* Cancel ongoing queue
*/
onCancel(): void;
setDestination(destination: Folder): void;
onUploadCompletion(upload: Upload): void;
onKeyDown(event: KeyboardEvent): void;
}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, Readonly<ExtractPropTypes<    {
accept: {
type: PropType<string[]>;
default: null;
};
disabled: {
type: BooleanConstructor;
default: boolean;
};
multiple: {
type: BooleanConstructor;
default: boolean;
};
/**
* Allow to disable the "new"-menu for this UploadPicker instance
*/
noMenu: {
type: BooleanConstructor;
default: boolean;
};
/**
* Allow to disable the button label
*/
noLabel: {
type: BooleanConstructor;
default: boolean;
};
/**
* Make the "New"-button primary color.
*/
primary: {
type: BooleanConstructor;
default: boolean;
};
destination: {
type: typeof Folder;
default: undefined;
};
allowFolders: {
type: BooleanConstructor;
default: boolean;
};
/**
* List of file present in the destination folder
* It is also possible to provide a function that takes a relative path to the current directory and returns the content of it
* Note: If a function is passed it should return the current base directory when no path or an empty is passed
*/
content: {
type: PropType<Node_2[] | ((relativePath?: string) => Node_2[] | PromiseLike<Node_2[]>)>;
default: () => never[];
};
/**
* Overwrite forbidden characters (by default the capabilities of the server are used)
* @deprecated Deprecated and will be removed in the next major version
*/
forbiddenCharacters: {
type: PropType<string[]>;
default: () => never[];
};
}>>, {
destination: Folder;
content: Node_2[] | ((relativePath?: string) => Node_2[] | PromiseLike<Node_2[]>);
primary: boolean;
accept: string[];
allowFolders: boolean;
disabled: boolean;
multiple: boolean;
noMenu: boolean;
noLabel: boolean;
forbiddenCharacters: string[];
}>;

export declare enum UploadStatus {
    INITIALIZED = 0,
    UPLOADING = 1,
    ASSEMBLING = 2,
    FINISHED = 3,
    CANCELLED = 4,
    FAILED = 5
}

export { }
