import type { DataSource, WatchResponse } from './squared';

import type { ExternalAsset } from './asset';
import type { IAbortComponent } from './core';
import type { PostFinalizeCallback } from './filemanager';
import type { SecureConfig } from './http';

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

import type { ServerOptions } from 'node:https';

// @ts-ignore
import type * as ws from 'ws';

export interface ISocketRequest {
    expires: number;
    readonly socketId: string;
    readonly id: string;
    get expired(): boolean;
}

export interface IFileGroup<T extends ExternalAsset = ExternalAsset> extends IAbortComponent {
    captured: boolean;
    port: number;
    secure: boolean;
    hot: boolean;
    always: boolean;
    id?: string;
    url?: URL;
    document?: string | string[];
    main?: T;
    bundleMain?: T;
    sourceFiles?: string[];
    readonly uri: string;
    readonly startTime: number;
    readonly assets: T[];
    readonly sockets: ISocketRequest[];
    add(expires: number, socketId?: string, id?: string): boolean;
    connection(server: ws.Server, port?: number, secure?: boolean): void;
    send(event: WatchEventValue, data: Partial<WatchResponse>): boolean;
    find(socketId: string): ISocketRequest | undefined;
    pause(): void;
    resume(): void;
    matchRecursive(value: string): boolean;
    get server(): ws.Server | null;
    set related(value);
    get related(): T[];
    get socketId(): string | string[];
    set etag(value: unknown);
    get etag(): string;
    set lastModified(value: unknown);
    get lastModified(): string;
    get expires(): number;
    get started(): boolean;
    get expired(): boolean;
    get paused(): boolean;
    get abortable(): boolean;
    get recursive(): boolean | undefined;
}

export interface FileGroupConstructor<T extends ExternalAsset = ExternalAsset> {
    CONNECTION_TIMEOUT: number;
    CLIENT_SESSION: Map<ws.WebSocket, number>;
    checkTimeout(client: ws.WebSocket): boolean;
    cloneAsset(asset: T): T;
    readonly prototype: IFileGroup<T>;
    new(uri: string, assets: T[], abortable: boolean, recursive?: boolean | string | string[]): IFileGroup<T>;
    new(uri: string, assets: T[], startTime?: number, abortable?: boolean, recursive?: boolean | string | string[]): IFileGroup<T>;
}

export interface WatchInitResult<T = ExternalAsset> {
    using?: T[];
    dataSource?: DataSource[];
}

export interface SecureOptions<T = string> extends SecureConfig<T> {
    config?: ServerOptions;
}

export type ModifiedPostFinalizeListener<T extends ExternalAsset = ExternalAsset> = (watch: IFileGroup<T>, assets?: T[]) => PostFinalizeCallback;