import { MainOptions } from '@ycmd/helpers';
import { SpawnOptions } from '@ycmd/spawn';
import { Logger } from '@ycmd/utils';
import { CommandBuilder, ArgumentsCamelCase } from 'yargs';

type Ctx = any;
interface CtxOptions {
    ctx: Ctx;
    cwd: string;
    args: string[];
    log: Logger;
}
interface RootRun extends CtxOptions {
    shell: string;
    filename: string;
}
interface PathexecCtx {
    rootRun: RootRun;
}
type PathexecProcess = typeof process & {
    pathexec?: PathexecCtx;
};
type LskrunProcess = typeof process & {
    lskrun?: RootRun;
    lskrunDisableAutorun?: boolean;
};
interface ShellOptions extends SpawnOptions {
    silence?: boolean | 'all';
    ctx?: any;
    args?: string[];
    argv?: Record<string, any>;
}
interface ShellParallelOptions extends ShellOptions {
    npmClient?: 'npm' | 'yarn' | 'pnpm';
    parallel?: boolean;
}
interface PathexecOptions extends SpawnOptions {
    args?: string[];
    argv?: Record<string, any>;
    log?: any;
    ctx?: any;
    cwd?: string;
    name?: string;
    cmdName?: string;
}
type MainFunction = (props: MainOptions) => Promise<any>;
type WrappedMainFunction = (props: any) => Promise<any>;
interface PartMainCommand {
    main?: MainFunction;
    meta?: ImportMeta;
}
interface MainCommand<T = {}, U = {}> extends PartMainCommand {
    /** array of strings (or a single string) representing aliases of `exports.command`, positional args defined in an alias are ignored */
    aliases?: ReadonlyArray<string> | string | undefined;
    /** object declaring the options the command accepts, or a function accepting and returning a yargs instance */
    builder?: CommandBuilder<T, U> | undefined;
    /** string (or array of strings) that executes this command when given on the command line, first string may contain positional args */
    command: ReadonlyArray<string> | string | undefined;
    /** boolean (or string) to show deprecation notice */
    deprecated?: boolean | string | undefined;
    /** string used as the description for the command in help text, use `false` for a hidden command */
    describe?: string | false | undefined;
    /** a function which will be passed the parsed argv. */
    handler?: (args: ArgumentsCamelCase<U>) => void | Promise<void>;
}
type CreateCommandParams = MainFunction | PartMainCommand | MainCommand;
type CreateCommandResult = MainCommand & {
    main: WrappedMainFunction;
    isWrapped: boolean;
    isAutorun: boolean;
    res?: any | Promise<any>;
};

export type { CreateCommandParams, CreateCommandResult, Ctx, CtxOptions, LskrunProcess, MainCommand, MainFunction, PartMainCommand, PathexecCtx, PathexecOptions, PathexecProcess, RootRun, ShellOptions, ShellParallelOptions, WrappedMainFunction };
