import { DecisionAnyMatch, InjectionResult } from "../constants.js";
import { Label } from "../logger.js";
import { Metafile } from "../parseTorrent.js";
import { Result } from "../Result.js";
import { File, Searchee, SearcheeWithInfoHash } from "../searchee.js";
import { ClientSearcheeResult, TorrentClient, TorrentMetadataInClient } from "./TorrentClient.js";
interface Preferences {
    resume_data_storage_type?: "Legacy" | "SQLite";
}
interface TorrentInfo {
    added_on: number;
    amount_left: number;
    auto_tmm: boolean;
    availability: number;
    category: string;
    comment?: string;
    completed: number;
    completion_on: number;
    connections_count?: number;
    connections_limit?: number;
    content_path: string;
    created_by?: string;
    creation_date?: number;
    dl_limit: number;
    dlspeed: number;
    download_path?: string;
    downloaded: number;
    downloaded_session: number;
    eta: number;
    f_l_piece_prio: boolean;
    files?: TorrentFile[];
    force_start: boolean;
    has_metadata?: boolean;
    hash: string;
    inactive_seeding_time_limit?: number;
    infohash_v1?: string;
    infohash_v2?: string;
    last_activity: number;
    magnet_uri: string;
    max_inactive_seeding_time?: number;
    max_ratio: number;
    max_seeding_time: number;
    name: string;
    num_complete: number;
    num_incomplete: number;
    num_leechs: number;
    num_seeds: number;
    piece_size?: number;
    pieces_have?: number;
    pieces_num?: number;
    popularity?: number;
    priority: number;
    private?: boolean;
    progress: number;
    ratio: number;
    ratio_limit: number;
    reannounce?: number;
    root_path?: string;
    save_path: string;
    seeding_time: number;
    seeding_time_limit: number;
    seen_complete: number;
    seq_dl: boolean;
    size: number;
    state: "error" | "missingFiles" | "uploading" | "pausedUP" | "stoppedUP" | "queuedUP" | "stalledUP" | "checkingUP" | "forcedUP" | "allocating" | "downloading" | "metaDL" | "pausedDL" | "stoppedDL" | "queuedDL" | "stalledDL" | "checkingDL" | "forcedDL" | "checkingResumeData" | "moving" | "unknown";
    super_seeding: boolean;
    tags: string;
    time_active: number;
    total_size: number;
    total_wasted?: number;
    tracker: string;
    trackers?: TorrentTracker[];
    trackers_count?: number;
    up_limit: number;
    uploaded: number;
    uploaded_session: number;
    upspeed: number;
}
interface TorrentTracker {
    msg: string;
    num_downloaded: number;
    num_leeches: number;
    num_peers: number;
    num_seeds: number;
    status: 0 | 1 | 2 | 3 | 4;
    tier: number;
    url: string;
}
interface TorrentFile {
    availability: number;
    index?: number;
    is_seed: boolean;
    name: string;
    piece_range: [number, number];
    priority: 0 | 1 | 6 | 7;
    progress: number;
    size: number;
}
interface CategoryInfo {
    name: string;
    savePath: string;
}
export default class QBittorrent implements TorrentClient {
    cookie: string;
    url: {
        username: string;
        password: string;
        href: string;
    };
    version: string;
    versionMajor: number;
    versionMinor: number;
    versionPatch: number;
    readonly clientHost: string;
    readonly clientPriority: number;
    readonly clientType = Label.QBITTORRENT;
    readonly readonly: boolean;
    readonly label: string;
    constructor(url: string, clientHost: string, priority: number, readonly: boolean);
    login(): Promise<void>;
    validateConfig(): Promise<void>;
    private request;
    getPreferences(): Promise<Preferences>;
    /**
     * Always returns "Original" for API searchees due to isSubfolderContentLayout.
     * This is not an issue since it's either a MATCH or we are linking.
     * @param searchee the Searchee the match was sourced from
     * @param searcheeInfo the torrent info from the searchee
     * @param destinationDir the destinationDir for the new torrent
     * @returns the layout to use for the new torrent
     */
    private getLayoutForNewTorrent;
    private getCategoryForNewTorrent;
    private getTagsForNewTorrent;
    createTag(): Promise<void>;
    createCategory(category: string, savePath: string): Promise<void>;
    editCategory(category: string, savePath: string): Promise<void>;
    getAllCategories(): Promise<CategoryInfo[]>;
    torrentFileToFile(torrentFile: TorrentFile): File;
    getFiles(infoHash: string): Promise<File[] | null>;
    getTrackers(infoHash: string): Promise<string[] | null>;
    addTorrent(formData: FormData): Promise<void>;
    recheckTorrent(infoHash: string): Promise<void>;
    getDownloadDir(meta: SearcheeWithInfoHash | Metafile, options: {
        onlyCompleted: boolean;
    }): Promise<Result<string, "NOT_FOUND" | "TORRENT_NOT_COMPLETE" | "INVALID_DATA" | "UNKNOWN_ERROR">>;
    getAllDownloadDirs(options: {
        metas: SearcheeWithInfoHash[] | Metafile[];
        onlyCompleted: boolean;
        v1HashOnly?: boolean;
    }): Promise<Map<string, string>>;
    getCorrectSavePath(data: Searchee | Metafile, torrentInfo: TorrentInfo): string;
    getAllTorrentInfo(options?: {
        includeFiles?: boolean;
        includeTrackers?: boolean;
    }): Promise<TorrentInfo[]>;
    getTorrentInfo(hash: string | undefined, numRetries?: number): Promise<TorrentInfo | undefined>;
    /**
     * @return array of all torrents in the client
     */
    getAllTorrents(): Promise<TorrentMetadataInClient[]>;
    /**
     * Get all searchees from the client and update the db
     * @param options.newSearcheesOnly only return searchees that are not in the db
     * @param options.refresh undefined uses the cache, [] refreshes all searchees, or a list of infoHashes to refresh
     * @param options.includeFiles include files in the torrents info request
     * @param options.includeTrackers include trackers in the torrents info request
     * @return an object containing all searchees and new searchees (refreshed searchees are considered new)
     */
    getClientSearchees(options?: {
        newSearcheesOnly?: boolean;
        refresh?: string[];
        includeFiles?: boolean;
        includeTrackers?: boolean;
    }): Promise<ClientSearcheeResult>;
    /**
     * @param inputHash the infohash of the torrent
     * @returns whether the torrent is in client
     */
    isTorrentInClient(inputHash: string): Promise<Result<boolean, Error>>;
    /**
     * @param infoHash the infohash of the torrent
     * @returns whether the torrent is complete
     */
    isTorrentComplete(infoHash: string): Promise<Result<boolean, "NOT_FOUND">>;
    /**
     * @param infoHash the infohash of the torrent
     * @returns whether the torrent is checking
     */
    isTorrentChecking(infoHash: string): Promise<Result<boolean, "NOT_FOUND">>;
    isTorrentInfoComplete(torrentInfo: TorrentInfo): boolean;
    /**
     * This can only return true if the searchee is from a torrent file, not API.
     * Since we get the file structure from the API, it's already accounted for.
     * This does NOT check if the torrent was added with "Don't Create Subfolder".
     * @param data the Searchee or Metafile
     * @param dataInfo the TorrentInfo
     * @returns whether the torrent was added with "Create Subfolder"
     */
    isSubfolderContentLayout(data: Searchee | Metafile, dataInfo: TorrentInfo): boolean;
    /**
     * This can only return true if the searchee is from a torrent file, not API.
     * Since we get the file structure from the API, it's already accounted for.
     * This does NOT check if the torrent was added with "Create Subfolder".
     * @param data the Searchee or Metafile
     * @param dataInfo the TorrentInfo
     * @returns whether the torrent was added with "Don't Create Subfolder"
     */
    isNoSubfolderContentLayout(data: Searchee | Metafile, dataInfo: TorrentInfo): boolean;
    resumeInjection(meta: Metafile, decision: DecisionAnyMatch, options: {
        checkOnce: boolean;
    }): Promise<void>;
    inject(newTorrent: Metafile, searchee: Searchee, decision: DecisionAnyMatch, options: {
        onlyCompleted: boolean;
        destinationDir?: string;
    }): Promise<InjectionResult>;
}
export {};
