import { VideoInfo as VideoInfo$2, VideoSource as VideoSource$1, VideoStore, EpisodeStore, MagnetStore, Episode } from '@animepaste/database';
export { VideoSource } from '@animepaste/database';
import Progress from 'cli-progress';
import * as mediainfo_js_dist_types from 'mediainfo.js/dist/types';
export { getBgmDmhy, getBgmId, getBgmLink, getBgmTitle } from '@animepaste/bangumi/utils';

type VideoStorePlatform = 'ali';
type VideoInfo$1 = VideoInfo$2<VideoStorePlatform>;

declare function b64encode(text: string): string;
declare function b64decode(text: string): string;
declare function hashFile(filepath: string): Promise<string>;
declare function createSingleProgress(): Progress.SingleBar;
interface ProgressBarOption<T> {
    suffix?: (value: number, total: number, payload: T) => string;
}
declare function createProgressBar<T extends object>(option?: ProgressBarOption<T>): {
    finish(): void;
    println(text: string): void;
    create(name: string, length: number): {
        update(value: number, payload?: T): void;
        increment(value: number, payload?: T): void;
    };
};

interface DownloadPayload {
    filepath: string;
    url: string;
}
declare function download(...payloads: DownloadPayload[]): Promise<void>;

interface VideoInfo<T extends string = string> {
    /**
     * Storage type, only supports Ali OSS
     *
     * @default 'ali'
     */
    platform: T;
    /**
     * Video ID
     */
    videoId: string;
    /**
     * Video title
     */
    title: string;
    /**
     * Creation time
     */
    createdAt: string;
    /**
     * Cover image
     */
    cover?: string;
    /**
     * Play urls
     */
    playUrl: string[];
    /**
     * Video source
     */
    source: VideoSource;
}
interface VideoSource {
    magnetId?: string;
    directory?: string;
    hash?: string;
}

type CreateStore = () => Promise<Store>;
declare abstract class Store {
    readonly platform: string;
    constructor(platform: string);
    init(): Promise<void>;
    protected abstract doFetchVideoInfo(videoId: string, option?: StoreOption): Promise<VideoInfo$1 | undefined>;
    protected abstract doUpload(filePath: string, option?: StoreOption): Promise<string | undefined>;
    protected abstract doDelete(videoId: string): Promise<boolean>;
    fetchVideoInfo(videoId: string): Promise<VideoInfo$1 | undefined>;
    searchLocalVideo(filename: string): Promise<VideoInfo$1[]>;
    listLocalVideos(): Promise<VideoInfo<"ali">[]>;
    deleteVideo(videoId: string): Promise<void>;
    upload(filepath: string, option?: StoreOption): Promise<VideoInfo$1 | undefined>;
}
interface StoreOption {
    /**
     * MagnetId
     */
    magnetId?: string;
    /**
     * Max retry number
     */
    retry?: number;
}

declare class AliStore extends Store {
    private readonly accessKeyId;
    private readonly accessKeySecret;
    private readonly regionId;
    private readonly vodClient;
    constructor(config: AliStoreConfig);
    private createUplodaVideo;
    doUpload(filepath: string, option?: StoreOption): Promise<string | undefined>;
    doDelete(videoId: string): Promise<boolean>;
    doFetchVideoInfo(videoId: string): Promise<VideoInfo$1 | undefined>;
}
declare const createAliStore: CreateStore;
interface AliStoreConfig {
    accessKeyId: string;
    accessKeySecret: string;
    regionId: string;
}
interface UploadResponse {
    VideoId: string;
    RequestId: string;
    UploadAddress: {
        Endpoint: string;
        Bucket: string;
        FileName: string;
    };
    UploadAuth: {
        SecurityToken: string;
        AccessKeyId: string;
        AccessKeySecret: string;
        Region: string;
        Expiration: string;
        ExpireUTCTime: string;
    };
}
interface Checkpoint {
    file: string;
    name: string;
    fileSize: number;
    partSize: number;
    uploadId: string;
    doneParts: Array<{
        number: number;
        etag: string;
    }>;
}

declare function useStore(type: 'ali'): CreateStore;

interface DownloadTask {
    magnetURI: string;
    filename?: string;
}
declare class TorrentClient {
    private readonly client;
    private readonly folder;
    constructor(folder: string);
    download(downloadTasks: DownloadTask[]): Promise<void>;
    destroy(): Promise<void>;
}

declare function closeMediaInfo(): Promise<void>;
declare function getVideoInfo(filepath: string): Promise<{
    general: mediainfo_js_dist_types.Track;
    video: mediainfo_js_dist_types.Track;
    audio: mediainfo_js_dist_types.Track;
}>;
declare function checkVideo(filepath: string): Promise<boolean>;

type AnimeType = 'tv' | 'web' | 'movie' | 'ova';
interface CliOption {
    force: boolean;
}
interface RawPlan {
    /**
     * Plan name
     */
    name: string;
    /**
     * Plan date
     */
    date: Date;
    /**
     * Plan is onair or finish
     *
     * @default 'onair'
     */
    state: 'onair' | 'finish';
    /**
     * Store platform
     *
     * @default 'ali'
     */
    store: VideoStorePlatform;
    /**
     * Template string for names
     *
     * @default '[{fansub}] {title} - S{season}E{ep}.mp4'
     */
    format?: string;
    /**
     * Enable upload bangumis to OSS
     *
     * @default true
     */
    sync: boolean;
    /**
     * Onair list
     */
    onair: OnairPlan[];
}
interface OnairPlan {
    /**
     * Anime name
     */
    title: string;
    /**
     * Anime season
     *
     * This value may be inferred from the title or be set with the default value 1
     */
    season: number;
    /**
     * Bangumi ID
     */
    bgmId: string;
    /**
     * Plan is onair or finish
     *
     * @default 'onair'
     */
    state: 'onair' | 'finish';
    /**
     * Fansub order
     */
    fansub?: string[];
    /**
     * Specify play link
     *
     * Type string for other platform
     *
     * Type record for play urls
     */
    link?: string | EpisodesInputList;
    /**
     * Specify the magnet id of some episode
     */
    magnet?: EpisodesInputList;
    /**
     * Specify OSS source of some episode
     */
    source?: EpisodesInputList;
    /**
     * Template string for names
     *
     * @default '[{fansub}] {title} - S{season}E{ep}.mp4'
     */
    format: string;
    /**
     * Enable upload bangumis to OSS
     *
     * @default true
     */
    sync: boolean;
    /**
     * Keywords for searching resources
     */
    keywords?: string[];
}
type EpisodesInputList = Record<number, string> | string[];

interface SearchOption {
    type: AnimeType;
    raw?: boolean;
    plan?: boolean;
    year?: string;
    month?: string;
    title?: string;
    fansub?: string[];
    log?: boolean;
    beginDate?: Date;
}
declare function userSearch(anime: string | undefined, option: SearchOption): Promise<void>;
declare function daemonSearch(bgmId: string, optionKeywords?: string[], option?: SearchOption): Promise<void>;
declare function search(bgm: {
    bgmId: string;
    titleCN: string;
}, keywords: string[], option?: SearchOption): Promise<void>;

declare function bangumiLink(bgmId: string): string;

interface OnairAnime {
    title: string;
    bgmId: string;
    episodes: (OnairEpisode | OnlineEpisode)[];
    link?: string;
}
interface OnlineEpisode {
    /**
     * 条目内的集数, 从 1 开始
     */
    ep: number;
    /**
     * Play url
     */
    playURL: string;
}
interface OnairEpisode {
    /**
     * 条目内的集数, 从 1 开始
     */
    ep: number;
    /**
     * Video qulity
     */
    quality: 1080 | 720;
    /**
     * Airdate
     */
    creationTime: string;
    /**
     * Play url
     */
    playURL: string;
    /**
     * Global storage config
     */
    storage: {
        type: string;
        videoId: string;
        source: VideoSource$1;
    };
}
interface UserOption {
    token: string;
    baseURL: string;
    onairIds?: Set<string>;
}

declare abstract class SyncClient {
    /**
     * Current onair bangumis
     */
    readonly onair: OnairAnime[];
    /**
     * Onair bangumis to be uploaded
     */
    readonly newOnair: OnairAnime[];
    abstract fetchOnair(): Promise<OnairAnime[]>;
    abstract syncOnair(): Promise<OnairAnime[]>;
    abstract removeOnair(bgmId: string): void;
    abstract updateOnair(onair: OnairAnime): void;
}

declare class LocalSyncClient extends SyncClient {
    static init(): Promise<LocalSyncClient>;
    fetchOnair(): Promise<OnairAnime[]>;
    syncOnair(): Promise<OnairAnime[]>;
    removeOnair(bgmId: string): void;
    updateOnair(onair: OnairAnime): void;
}

declare class RemoteSyncClient extends SyncClient {
    private static MAX_RETRY;
    private readonly token;
    private readonly api;
    /**
     * Mark whether onair  anime is changed
     */
    private dirty;
    /**
     * Filter all the ids of onair bangumis
     */
    readonly onairIds: Set<string> | undefined;
    constructor(option: UserOption);
    static create(onairIds?: Set<string>): Promise<RemoteSyncClient>;
    static init(): Promise<RemoteSyncClient>;
    fetchOnair(): Promise<OnairAnime[]>;
    syncOnair(): Promise<OnairAnime[]>;
    removeOnair(bgmId: string): void;
    updateOnair(onair: OnairAnime): void;
    createToken(payload: TokenPayload): Promise<Required<TokenPayload> | undefined>;
    listToken(): Promise<Required<TokenPayload & {
        access: Access[];
    }>[]>;
    removeToken(token: string): Promise<boolean>;
    removeVisitors(): Promise<string[] | undefined>;
}
interface TokenPayload {
    token?: string;
    type?: 'user' | 'admin' | 'visitor';
    comment?: string;
}
interface Access {
    ip: string;
    count: number;
    timestamp: number;
}

declare function initClient(): Promise<LocalSyncClient | RemoteSyncClient>;

interface GlobalConfig {
    plans: string | string[];
    sync: {
        local?: boolean;
        remote?: {
            baseURL: string;
            token: string;
        };
    };
    store: {};
}
declare class GlobalContex {
    static SpaceDirectory: string;
    static ConfigFilename: string;
    static DatabaseFilename: string;
    cliOption: CliOption;
    isDaemon: boolean;
    readonly root: string;
    readonly config: string;
    readonly databaseFilepath: string;
    readonly videoStore: VideoStore<VideoStorePlatform>;
    readonly episodeStore: EpisodeStore;
    readonly magnetStore: MagnetStore;
    private _cacheRoot;
    private _localRoot;
    private configCache;
    constructor();
    get localRoot(): string;
    get cacheRoot(): string;
    init(option: CliOption): Promise<void>;
    makeLocalAnimeRoot(title: string): Promise<string>;
    loadConfig<T = any>(): Promise<T>;
    getPlans(): Promise<RawPlan[]>;
    getSyncConfig(): Promise<GlobalConfig['sync']>;
    getRemoteConfig(): Promise<GlobalConfig['sync']['remote']>;
    getStoreConfig<T = any>(key: string): Promise<T>;
    /**
     * Copy file from "src" to cache root
     *
     * @param src
     */
    copyToCache(src: string): Promise<string>;
    formatOnlineURL(baseURL: string, bgmId: string): string;
    encodePath(src: string): string;
    decodePath(src: string, filename?: string): string;
}
declare const context: GlobalContex;

interface DaemonStepOption {
    /**
     * Filter onair plan
     */
    filter?: (onair: OnairPlan) => boolean;
    /**
     * Enable log
     */
    log?: boolean;
}
declare class Daemon {
    private plan;
    private store;
    private client;
    /**
     * Enable index
     *
     * @default 'true'
     */
    private readonly enableIndex;
    /**
     * Enable upload
     *
     * @default 'true'
     */
    private readonly enableUpload;
    /**
     * Enable sync onair list
     *
     * @default 'true'
     */
    private readonly enableSync;
    constructor(option: {
        index: boolean;
        upload: boolean;
        sync: boolean;
    });
    init(): Promise<void>;
    update(): Promise<void>;
    initPlan({ log }?: DaemonStepOption): Promise<void>;
    initClient(): Promise<void>;
    private refreshDatabase;
    /**
     * Refresh episode magnet list
     *
     * Prerequisite: this.initPlan(), this.initClient()
     */
    refreshEpisode({ log, filter }?: DaemonStepOption): Promise<void>;
    private refreshStore;
    private refreshAnime;
    private syncPlaylist;
}

declare class Plan {
    private readonly baseURL;
    private readonly plans;
    constructor(option: {
        baseURL: string;
        plans: RawPlan[];
    });
    static create(): Promise<Plan>;
    [Symbol.iterator](): IterableIterator<RawPlan>;
    onairs(): OnairPlan[];
    printOnair(): void;
    genEpisodes(allEpisodes: Episode[], fansubOrder: string[]): Episode[];
}

declare function startDaemon(option: {
    once: boolean;
    interval: number;
    index: boolean;
    upload: boolean;
    sync: boolean;
}): Promise<void>;
declare function createDaemon(index?: boolean): Daemon;

export { AliStore, AliStoreConfig, Checkpoint, CreateStore, DownloadPayload, GlobalConfig, GlobalContex, OnairAnime, OnairEpisode, OnlineEpisode, Plan, ProgressBarOption, RemoteSyncClient, Store, StoreOption, SyncClient, TorrentClient, UploadResponse, UserOption, VideoInfo$1 as VideoInfo, VideoStorePlatform, b64decode, b64encode, bangumiLink, checkVideo, closeMediaInfo, context, createAliStore, createDaemon, createProgressBar, createSingleProgress, daemonSearch, download, getVideoInfo, hashFile, initClient, search, startDaemon, useStore, userSearch };
