import type { LogStatus } from './squared';

import type { HighResolutionTime } from './node';

import type { LOG_STATE, LOG_TYPE, STATUS_TYPE } from '../index.d';

// @ts-ignore
import type { BackgroundColor as IBackgroundColor, ForegroundColor as IForegroundColor } from 'chalk';

type HexColor = `#${string}`;

export interface LogBaseOptions extends LoggerColor, Pick<LogOptions, "queue" | "timeStamp"> {
    type?: LogType;
    statusType?: StatusType;
    sessionId?: string;
    abortable?: boolean;
    titleJustify?: TextAlign;
    rawOutput?: boolean;
    broadcastId?: BroadcastValue;
    newline?: boolean | number;
}

export interface LoggerColor {
    titleColor?: ForegroundColor;
    titleBgColor?: BackgroundColor;
    titleBold?: boolean;
    valueColor?: ForegroundColor;
    valueBgColor?: BackgroundColor;
    valueBold?: boolean;
    hintColor?: ForegroundColor;
    hintBgColor?: BackgroundColor;
    hintBold?: boolean;
    messageColor?: ForegroundColor;
    messageBgColor?: BackgroundColor;
    messageBold?: boolean;
}

export interface LoggerStatus<T = boolean> {
    fatal?: T;
    error?: T;
    warn?: T;
    info?: T;
    debug?: T;
    trace?: T;
}

export interface LogOptions extends Partial<Pick<LogStatus<StatusType>, "duration" | "from" | "source">> {
    queue?: boolean;
    timeStamp?: LogDate;
}

export interface LogMessageOptions extends LogBaseOptions {
    failed?: boolean;
    useColor?: boolean;
    messageWidth?: number;
    messageUnit?: string;
    messageUnitMinWidth?: number;
    messageUnitIndent?: number | [number, string];
    messageTextWrap?: boolean | TextWrapStyle;
    progressBar?: boolean;
    alwaysVisible?: boolean;
    titleIndent?: boolean | number;
}

export interface LogFailOptions extends LogBaseOptions {
    exec?: ExecCommand;
    code?: string;
    fatal?: boolean;
    passThrough?: boolean;
    startTime?: LogTime;
}

export interface LogProcessOptions extends LogMessageOptions {
    bypassLog?: boolean;
    meterIncrement?: number;
    delayTime?: number | HighResolutionTime;
}

export interface LogTimeElapsedOptions extends LogMessageOptions {
    showCpu?: boolean;
}

export interface LogTypeValue {
    type: LogType;
    value: LogValue;
    timeStamp: number;
    sessionId?: string;
}

export interface LogArguments extends Pick<LogBaseOptions, "type" | "sessionId"> {
    title?: string;
    value?: LogValue;
    message?: unknown;
}

export interface ExecCommand {
    command: string;
    args?: string[];
    warn?: string[];
}

export type { LOG_STATE, LOG_TYPE, STATUS_TYPE };
export type LogType = LOG_TYPE[keyof LOG_TYPE];
export type StatusType = STATUS_TYPE[keyof STATUS_TYPE];
export type LogState = LOG_STATE[keyof LOG_STATE];
export type StatusName = keyof typeof STATUS_TYPE;
export type LogDate = Date | number;
export type LogTime = LogDate | HighResolutionTime;
export type LogValue = string | [string, (string | null)?];
export type LogComponent = Partial<Pick<LogStatus<StatusType>, "type" | "value" | "timeStamp" | "duration" | "from" | "source">>;
export type BackgroundColor = typeof IBackgroundColor | HexColor;
export type ForegroundColor = typeof IForegroundColor | HexColor;
export type TextAlign = "left" | "center" | "right";
export type TextWrapStyle = "ellipsis" | "nowrap" | "ellipsis-end" | "nowrap-end" | "none";
export type ErrorOutMethod = (err: Error, data: LogTypeValue, require?: NodeJS.Require) => void;
export type BroadcastOutMethod = (value: string, options: LogMessageOptions, require?: NodeJS.Require) => void;
export type BroadcastValue = string | string[] | { value: string | string[]; stripAnsi?: boolean };