import { Sade } from "sade";
import { Box } from "getbox";

//#region src/types.d.ts
type Spread<T$1> = { [K in keyof T$1]: T$1[K] } & {};
type Merge<T$1, U> = Omit<T$1, keyof U> & U;
type IsCapitalized<T$1 extends string> = Uncapitalize<T$1> extends T$1 ? false : true;
type CamelToKebabCaseKey<T$1 extends PropertyKey, A extends string = ""> = T$1 extends string ? T$1 extends `${infer P}${infer S}` ? Uncapitalize<S extends "" ? `${A}${P}` : IsCapitalized<S> extends true ? `${A}${P}-${CamelToKebabCaseKey<Uncapitalize<S>>}` : CamelToKebabCaseKey<S, `${A}${P}`>> : T$1 : never;
type StripNegated<T$1 extends PropertyKey> = T$1 extends `no-${infer U}` ? U : T$1;
type MapUnion<T$1 extends string, U extends Record<T$1, any>> = U extends Record<T$1, any> ? U : never;
type KnownKey<T$1> = string extends T$1 ? never : number extends T$1 ? never : symbol extends T$1 ? never : T$1;
type Invalid<Message extends string> = never;
//#endregion
//#region src/arg.d.ts
type ArgType = "required" | "optional";
type ArgTypeToValue<T$1 extends ArgType> = MapUnion<T$1, {
  required: string;
  optional: string | undefined;
}>[T$1];
type ParsedArgs<Args extends Record<string, Arg>> = { [K in keyof Args as KnownKey<K>]: Args[K] extends Arg<infer T> ? ArgTypeToValue<T> : never };
declare class Arg<T$1 extends ArgType = ArgType> {
  private _type;
  constructor(_type: T$1);
  optional(): Arg<"optional">;
  static toObject(arg: Arg): {
    type: ArgType;
  };
  static toString(arg: Arg, name: string): string;
}
declare function arg(): Arg<"required">;
//#endregion
//#region src/flag.d.ts
type ParamType = "string" | "number" | "array";
type ParamTypeToValue<T$1 extends ParamType> = MapUnion<T$1, {
  string: string;
  number: number;
  array: string[];
}>[T$1];
type OptionalParam<T$1 extends ParamType, D extends ParamTypeToValue<T$1> | undefined> = {
  _type: "optional";
  type: T$1;
  defaultValue: D;
};
type RequiredParam<T$1 extends ParamType> = {
  _type: "required";
  type: T$1;
};
type FlagKey<F extends Record<string, Flag>, K$1 extends keyof F> = F[K$1] extends Flag<infer TFlag> ? (TFlag["preserveCase"] extends true ? StripNegated<K$1> : StripNegated<CamelToKebabCaseKey<K$1>>) | (TFlag["char"] extends string ? TFlag["char"] : never) : never;
type TFlag = {
  char?: string;
  param?: OptionalParam<any, any> | RequiredParam<any>;
  preserveCase?: boolean;
};
type Replace<T$1, K$1 extends keyof T$1, N extends T$1[K$1]> = Spread<Omit<T$1, K$1> & { [k in K$1]: N }>;
type Remove<T$1, K$1 extends keyof T$1> = Spread<Omit<T$1, K$1>>;
type ParsedFlags<Flags extends Record<string, Flag>> = { [K in keyof Flags as KnownKey<FlagKey<Flags, K>>]: Flags[K] extends Flag<infer T> ? T["param"] extends RequiredParam<infer Type> ? ParamTypeToValue<Type> : T["param"] extends OptionalParam<infer Type, infer D> ? undefined extends D ? ParamTypeToValue<Type> | undefined : ParamTypeToValue<Type> : T["param"] extends undefined ? boolean : unknown extends T["param"] ? boolean : boolean | number | string | string[] : never };
declare class Flag<T$1 extends TFlag = TFlag> {
  private _desc;
  private _char;
  private _param;
  private _preserveCase;
  private _negate;
  constructor(_desc: string, _char: T$1["char"], _param: T$1["param"], _preserveCase: T$1["preserveCase"], _negate: string | undefined);
  char<C extends string>(char: C): Flag<Replace<T$1, "char", C>>;
  requiredParam<U extends ParamType>(type: U): Flag<Replace<T$1, "param", RequiredParam<U>>>;
  optionalParam<U extends ParamType, D extends ParamTypeToValue<U> | undefined = undefined>(type: U, defaultValue?: D): Flag<Replace<T$1, "param", OptionalParam<U, D>>>;
  withNegated(description: string): Flag<Remove<T$1, "param">>;
  preserveCase(): Flag<Replace<T$1, "preserveCase", true>>;
  static toObject(flag: Flag): {
    desc: string;
    char: string | undefined;
    param: OptionalParam<any, any> | RequiredParam<any> | undefined;
    negate: string | undefined;
    preserveCase: boolean | undefined;
  };
  static toString(flag: Flag, name: string): string;
  static toNegatedString(flag: Flag, name: string): string;
  static isNegated(str: string): boolean;
  static toKebabCase(str: string): string;
}
declare function flag(description: string): Flag<{}>;
//#endregion
//#region src/command.d.ts
type SubcommandOptions<ProgramFlags extends Record<string, Flag>> = {
  program: Sade;
  programFlags: ProgramFlags;
  baseCmd?: string | undefined;
  defaultCmd?: Command<any, any, any, ProgramFlags>;
};
type CommandOptions<Name extends string, Args extends Record<string, Arg>, Flags extends Record<string, Flag>, ProgramFlags extends Record<string, Flag>> = {
  name: Name;
  description: string | undefined;
  aliases: string[];
  examples: string[];
  args: Args;
  flags: Flags;
  action: (ctx: {
    args: ParsedArgs<Args>;
    flags: ParsedFlags<Merge<ProgramFlags, Flags>>;
    restArgs: string[];
  }, box: Box) => any | Promise<any>;
  subcommands: Command<any, any, any, ProgramFlags>[];
};
type AnyCommand = Command<any, any, any, any>;
declare class Command<Name extends string, Args extends Record<string, Arg>, Flags extends Record<string, Flag>, ProgramFlags extends Record<string, Flag>> {
  private options;
  constructor(options: CommandOptions<Name, Args, Flags, ProgramFlags>);
  command(box: Box, options: SubcommandOptions<ProgramFlags>): void;
}
declare class CommandBuilder<Name extends string, Args extends Record<string, Arg>, Flags extends Record<string, Flag>, ProgramFlags extends Record<string, Flag>> {
  private options;
  constructor(name: Name);
  describe(description: string): this;
  alias(...aliases: string[]): this;
  example(example: string): this;
  args<A extends (Record<string, Arg> extends Args ? Record<string, Arg> : Invalid<"args can only be set once">)>(args: A): Record<string, Arg> extends Args ? CommandBuilder<Name, A, Flags, ProgramFlags> : never;
  flags<F extends (Record<string, Flag> extends Flags ? Record<string, Flag> : Invalid<"flags can only be set once">)>(flags: F): Record<string, Flag> extends Flags ? CommandBuilder<Name, Args, F, ProgramFlags> : never;
  programFlags<F extends (Record<string, Flag> extends ProgramFlags ? Record<string, Flag> : Invalid<"programFlags can only be set once">)>(): Record<string, Flag> extends ProgramFlags ? CommandBuilder<Name, Args, Flags, F> : never;
  subcommands<C extends Command<any, any, any, ProgramFlags>[]>(...commands: C): this;
  action(fn: (ctx: {
    args: Spread<ParsedArgs<Args>>;
    flags: Spread<ParsedFlags<Merge<ProgramFlags, Flags>>>;
    restArgs: string[];
  }, box: Box) => any | Promise<any>): Command<Name, Args, Flags, ProgramFlags>;
}
declare function command<Name extends string>(name: Name): CommandBuilder<Name, {}, {}, {}>;
//#endregion
//#region src/errors.d.ts
declare class CommandError extends Error {
  reason: "invalid_arg" | "invalid_flag";
  message: string;
  constructor(reason: "invalid_arg" | "invalid_flag", message: string);
}
//#endregion
//#region src/run.d.ts
type RunOptions = {
  errorOnUnknown?: boolean | ((flag: string) => string);
  onError?(err: any): void;
};
declare function run(cli: Sade, options?: RunOptions, argv?: string[]): Promise<any>;
//#endregion
//#region src/program.d.ts
type ProgramOptions<Name extends string, Flags extends Record<string, Flag>> = {
  name: Name;
  version: string | undefined;
  description: string | undefined;
  examples: string[];
  flags: Flags;
  commands: Command<any, any, any, Flags>[];
  default: Command<any, any, any, Flags> | undefined;
};
type AnyProgram = Program<any, any>;
declare class Program<Name extends string, Flags extends Record<string, Flag>> {
  private box;
  private options;
  constructor(box: Box, options: ProgramOptions<Name, Flags>);
  program(): Sade;
  run(options?: RunOptions, argv?: string[]): Promise<any>;
}
declare class ProgramBuilder<Name extends string, Flags extends Record<string, Flag>> {
  private box;
  private options;
  constructor(box: Box, name: Name);
  version(version: string): this;
  describe(description: string): this;
  example(example: string): this;
  flags<F extends (Record<string, Flag> extends Flags ? Record<string, Flag> : never)>(flags: F): Record<string, Flag> extends Flags ? ProgramBuilder<Name, F> : never;
  commands<C extends Command<any, any, any, Flags>[]>(...commands: C): this;
  default(command: Command<any, any, any, Flags>): this;
  build(): Program<Name, Flags>;
}
declare function program<Name extends string>(name: Name, box?: Box): ProgramBuilder<Name, Record<string, Flag<{
  char?: string;
  param?: {
    _type: "optional";
    type: any;
    defaultValue: any;
  } | {
    _type: "required";
    type: any;
  };
  preserveCase?: boolean;
}>>>;
//#endregion
//#region src/single.d.ts
type SingleProgramOptions<Name extends string, Args extends Record<string, Arg>, Flags extends Record<string, Flag>> = {
  name: Name;
  version: string | undefined;
  description: string | undefined;
  examples: string[];
  args: Args;
  flags: Flags;
  action: (ctx: {
    args: ParsedArgs<Args>;
    flags: ParsedFlags<Flags>;
    restArgs: string[];
  }, box: Box) => any | Promise<any>;
};
type AnySingleProgram = SingleProgram<any, any, any>;
declare class SingleProgram<Name extends string, Args extends Record<string, Arg>, Flags extends Record<string, Flag>> {
  private box;
  private options;
  constructor(box: Box, options: SingleProgramOptions<Name, Args, Flags>);
  program(): Sade;
  run(options?: RunOptions, argv?: string[]): Promise<any>;
}
declare class SingleProgramBuilder<Name extends string, Args extends Record<string, Arg>, Flags extends Record<string, Flag>> {
  private box;
  private options;
  constructor(box: Box, name: Name);
  version(version: string): this;
  describe(description: string): this;
  example(example: string): this;
  args<A extends (Record<string, Arg> extends Args ? Record<string, Arg> : Invalid<"args can only be set once">)>(args: A): Record<string, Arg> extends Args ? SingleProgramBuilder<Name, A, Flags> : never;
  flags<F extends (Record<string, Flag> extends Flags ? Record<string, Flag> : Invalid<"flags can only be set once">)>(flags: F): Record<string, Flag> extends Flags ? SingleProgramBuilder<Name, Args, F> : never;
  action(fn: (ctx: {
    args: Spread<ParsedArgs<Args>>;
    flags: Spread<ParsedFlags<Flags>>;
    restArgs: string[];
  }, box: Box) => any | Promise<any>): SingleProgram<Name, Args, Flags>;
}
declare function singleProgram<Name extends string>(name: Name, box?: Box): SingleProgramBuilder<Name, {}, {}>;
//#endregion
export { type AnyCommand, type AnyProgram, type AnySingleProgram, Arg, Command, CommandError, Flag, Program, type RunOptions, SingleProgram, arg, command, flag, program, run, singleProgram };