import type { BundleAction, ChecksumOutput, EncodingAction, FileInfo, LogStatus } from './squared';

import type { IFileManager, IImage, IModule, ImageConstructor, ModuleConstructor } from './index';
import type { ExternalAsset } from './asset';
import type { HostInitLog as IHostInitLog } from './core';
import type { ReadHashOptions } from './module';
import type { RequestData as IRequestData } from './node';
import type { RequestInit } from './request';

import type { FETCH_TYPE } from '../index.d';

export const enum FINALIZE_STATE {
    READY,
    COMMIT,
    END,
    RESTART,
    QUEUED,
    RESTARTED,
    ABORTED
}

export const enum INCREMENTAL {
    NONE = 'none',
    STAGING = 'staging',
    ETAG = 'etag',
    EXISTS = 'exists'
}

export interface RequestData<T extends ExternalAsset = ExternalAsset, U extends HostInitLog = HostInitLog> extends IRequestData<T, U>, RequestInit {
    timeout?: ObjectMap<number | string>;
}

export interface InstallData<T extends IModule = IModule, U extends ModuleConstructor = ModuleConstructor> {
    instance: T;
    constructor: U;
    params: unknown[];
}

export interface IHttpDiskCache<T extends ExternalAsset = ExternalAsset> {
    limit: number;
    expires: number;
    readonly host: IFileManager<T>;
    has(uri: string | URL): boolean;
    add<U extends HttpDiskCacheAddOptions>(uri: string | URL, etag: string, target: Bufferable, options?: U): void;
    within(value: T | number): boolean;
    clear(value?: unknown): void;
    set enabled(value);
    get enabled(): boolean;
    set exclude(value);
    get exclude(): string[];
    set include(value);
    get include(): string[];
}

export interface IHttpMemoryCache<T extends ExternalAsset = ExternalAsset> extends IHttpDiskCache<T> {
    toDisk: [number, number];
    purge(percent?: number, limit?: number): void;
    withinDisk(value: T | number): boolean;
    clear(uri?: string | URL): void;
}

export interface HttpDiskCacheAddOptions {
    buffer?: Bufferable | null;
    contentLength?: number;
}

export interface HttpMemoryCacheAddOptions extends Omit<HttpDiskCacheAddOptions, "buffer">, EncodingAction {
    toDisk?: string;
}

export interface ReplaceOptions {
    mimeType?: string;
    rewritePath?: boolean;
    ignoreExt?: boolean;
}

export interface AssetContentOptions extends BundleAction {
    localUri: string;
}

export interface FileOutput {
    pathname: string;
    localUri: string;
}

export interface FinalizeResult {
    files: FileInfo[];
    errors: string[];
    status?: LogStatus[];
    aborted?: boolean;
}

export interface DeleteFileAddendum {
    id?: number;
    all?: boolean;
}

export interface HostInitLog extends IHostInitLog {
    useNumeric: boolean;
    showSize?: boolean;
    showDiff?: string[];
}

export interface FindAssetOptions<T extends ExternalAsset = ExternalAsset> {
    instance?: IModule;
    assets?: T[];
    replaced?: boolean;
}

export interface ChecksumOptions extends ReadHashOptions, Pick<ChecksumOutput, "include" | "exclude" | "recursive"> {
    dot?: boolean;
    matchBase?: boolean;
    sortBy?: number;
    verbose?: boolean;
    ignore?: string[];
    ignoreRoot?: string[];
    joinRoot?: boolean;
    outPath?: string;
    throwsEmpty?: boolean;
}

export interface CheckHashOptions {
    data?: Bufferable | null;
    uri?: string | URL;
    output?: boolean;
}

export type ImageMimeMap = Map<string, InstallData<IImage, ImageConstructor>>;
export type FetchType = FETCH_TYPE[keyof FETCH_TYPE];
export type PostFinalizeCallback = (files: FileInfo[] | string[], errors: string[], status?: LogStatus[]) => void;