import type { BundleAction, FileAsset, LocationUri, MimeTypeAction } from './squared';

import type { IFileManager, IModule } from './index';
import type { IAbortComponent } from './core';
import type { FetchType } from './filemanager';

interface ProcessInit {
    threadCount: number;
    startTime: number;
    timeout: number;
}

export interface BinaryAction {
    binOpts?: string[];
    shellExpansion?: boolean;
}

export interface StreamAction {
    minStreamSize?: number | string;
}

export interface FileData<T extends ExternalAsset> extends MimeTypeAction {
    file: T;
}

export interface FileCommand<T extends ExternalAsset> extends FileData<T> {
    command?: string;
    outputType?: string;
}

export interface IFileThread<T extends ExternalAsset = ExternalAsset> extends IAbortComponent, Required<FileData<T>> {
    threadCount: number;
    readonly startTime: number;
    openThread(instance: IModule, timeout?: number): boolean;
    closeThread(instance: IModule, callback?: FunctionType<void>): boolean;
    getObject<U extends FileCommand<T>>(data?: PlainObject): U;
    get host(): IFileManager<T>;
    get queuedTasks(): FunctionType<void>[];
    get localUri(): string | undefined;
}

export interface FileThreadConstructor<T extends ExternalAsset = ExternalAsset> {
    readonly prototype: IFileThread<T>;
    new(host: IFileManager<T>, file: ExternalAsset, threadCount: number): IFileThread<T>;
}

export interface OutputFinalize<T extends ExternalAsset> extends FileCommand<T> {
    output: string;
    baseDirectory?: string;
}

export interface InitialValue extends Partial<LocationUri>, MimeTypeAction {
    localUri?: string;
    buffer?: Buffer;
    etag?: string;
    cacheable?: boolean;
}

export interface ExternalAsset extends FileAsset, BundleAction, BinaryAction, StreamAction {
    id?: number;
    url?: URL;
    socketPath?: string;
    buffer?: Buffer | null;
    localUri?: string;
    fetchType?: FetchType;
    sourceUTF8?: string;
    transforms?: string[];
    descendants?: string[];
    torrentFiles?: string[];
    sourceFiles?: string[];
    initialValue?: InitialValue;
    processModule?: ObjectMap<ProcessInit>;
    etag?: string;
    lastModified?: string;
    contentLength?: number;
    invalid?: boolean;
}

export type HashAlgorithm = "md5" | "sha1" | "sha256" | "sha224" | "sha384" | "sha512" | "ripemd" | "ripemd-160";