import { ParsedArgumentsCollection } from "./classes";
/**
 * Represents the type of argument.
 *
 * @category Types
 */
export type ArgType = 'string' | 'number' | 'boolean';
/**
 * The type of nargs. It can be a number, or one of the following symbols:
 * - `?`: The argument is optional.
 * - `*`: The argument is optional and can appear multiple times.
 * - `+`: The argument is required and can appear multiple times.
 *
 * @category Types
 */
export type NArgs = number | '?' | '*' | '+';
/**
 * Predefined actions for the argument parser.
 *
 * @category Types
 */
export type PredefinedAction = 'version' | 'help';
/**
 * A function that takes a value and does something with it.
 *
 * @category Types
 */
export type ActionFunction = ((value: unknown, parsed: ParsedArgumentsCollection, parser: ArgsParserInterface) => void);
/**
 * An action that can be used with the argument parser.
 * It can be a predefined action or a function that takes a value
 * and does something with it.
 *
 * @category Types
 */
export type Action = PredefinedAction | ActionFunction;
/**
 * Router action function.
 */
export type RouterAction = (parser: ArgsParserInterface, args: string[]) => (void | Promise<void>);
/**
 * Configuration for the argument parser.
 *
 * @category Types
 */
export type ArgParserConfig = {
    /**
     * The name of the program.
     */
    name?: string;
    /**
     * The version of the program.
     */
    version?: string;
    /**
     * Whether to exit the program on error (true by default).
     */
    exitOnError?: boolean;
    /**
     * Whether to exit the program on StopException (true by default).
     */
    exitOnStop?: boolean;
    /**
     * Whether to ignore unrecognized arguments (false by default).
     */
    ignoreUnrecognized?: boolean;
};
/**
 * Configuration for an argument.
 *
 * @category Types
 */
export type ArgConfig = {
    /**
     * The type of the argument.
     */
    type: ArgType;
    /**
     * The name of the argument.
     */
    name: string;
    /**
     * An optional alias for the argument.
     */
    alias?: string;
    /**
     * A description of the argument.
     */
    description?: string;
    /**
     * Whether the argument is required.
     */
    nargs?: NArgs;
    /**
     * Whether the argument is required.
     */
    required?: boolean;
    /**
     * The default value of the argument.
     */
    default?: unknown;
    /**
     * A constant value for the argument.
     */
    const?: unknown;
    /**
     * Allowed values for the argument.
     */
    choices?: unknown[];
    /**
     * A custom action for the argument.
     */
    action?: Action;
    /**
     * A custom validator function for the argument value.
     */
    validator?: (value: unknown) => boolean;
};
/**
 * Configuration for an action used with the argument parser.
 *
 * @category Types
 */
export type ActionConfig = {
    /**
     * The name of the action.
     */
    name: string;
    /**
     * An optional alias for the action.
     */
    alias?: string;
    /**
     * A description of the action.
     */
    description?: string;
    /**
     * The action to be performed.
     */
    action: Action;
};
/**
 * ArgConfig extension.
 *
 * @category Types
 */
export type ArgExtraConfig = {
    /**
     * If the argument is positional.
     */
    positional: boolean;
    /**
     * If the argument is multiple.
     */
    multiple: boolean;
    /**
     * If the argument is required.
     */
    required: boolean;
    /**
     * If the argument is allowed to be empty.
     */
    allowEmpty: boolean;
    /**
     * The minimum number of times the argument is allowed to appear.
     */
    minValuesCount: number;
    /**
     * The number of times the argument is allowed to appear.
     * If not defined, it means the argument can appear any number of times.
     */
    valuesCount?: number;
};
/**
 * Extended configuration for an argument, combining both input and extra configurations.
 *
 * @category Types
 */
export type ArgConfigExtended = ArgConfig & ArgExtraConfig;
/**
 * Interface for a collection of parsed arguments.
 *
 * @category Interfaces
 */
export interface ParsedArgumentsCollectionInterface {
    /**
     * All positional arguments as a record.
     */
    readonly positional: Record<string, unknown>;
    /**
     * All optional arguments as a record.
     */
    readonly options: Record<string, unknown>;
    /**
     * Retrieves an argument value by name.
     *
     * @param name - The name of the argument.
     *
     * @returns The value of the argument.
     */
    get<T = unknown>(name: string): T;
    /**
     * Checks if an argument exists in the collection.
     *
     * @param name - The name of the argument.
     *
     * @returns True if the argument exists, false otherwise.
     */
    has(name: string): boolean;
}
/**
 * Interface for an argument parser.
 *
 * @category Interfaces
 */
export interface ArgsParserInterface {
    /**
     * The configuration of the argument parser.
     */
    readonly config: ArgParserConfig;
    /**
     * The help message for the arguments.
     */
    readonly help: string;
    /**
     * Adds an argument configuration to the parser.
     *
     * @param config - The argument configuration.
     *
     * @returns The updated parser.
     */
    addArgument(config: ArgConfig): ArgsParserInterface;
    /**
     * Adds an action configuration to the parser.
     *
     * @param config - The action configuration.
     *
     * @returns The updated parser.
     */
    addAction(config: ActionConfig): ArgsParserInterface;
    /**
     * Adds a help action to the parser.
     *
     * @param name - The name of the help action.
     * @param alias - The alias of the help action.
     *
     * @returns The updated parser.
     */
    addHelpAction(name?: string, alias?: string): ArgsParserInterface;
    /**
     * Adds a version action to the parser.
     *
     * @param name - The name of the version action.
     * @param alias - The alias of the version action.
     *
     * @returns The updated parser.
     */
    addVersionAction(name?: string, alias?: string): ArgsParserInterface;
    /**
     * Parses the given argument string and returns a collection of parsed arguments.
     *
     * @param argv - The argument string.
     *
     * @returns A ParsedArgumentsCollection containing the parsed arguments.
     */
    parse(argv: string[]): ParsedArgumentsCollectionInterface;
}
/**
 * Interface for a value validator.
 *
 * @category Interfaces
 */
export interface ValueValidatorInterface {
    /**
     * Validates the argument value before casting.
     *
     * @param value - The value to validate.
     * @param isset - Whether the value is set.
     *
     * @throws ArgumentValueError if the value is invalid.
     */
    validateBeforeCast(value: string[], isset: boolean): void;
    /**
     * Validates the argument value after casting.
     *
     * @param value - The value to validate.
     *
     * @throws ArgumentValueError if the value is invalid.
     */
    validateAfterCast(value: string[]): void;
}
/**
 * Interface for a value caster.
 *
 * @template T - The expected type of the argument value.
 *
 * @category Interfaces
 */
export interface ValueCasterInterface<T> {
    /**
     * Casts the argument value to the expected type.
     *
     * @param value - The value to cast.
     * @param isset - Whether the value is set.
     *
     * @returns The casted value.
     */
    cast(value: string[], isset: boolean): T | undefined;
}
/**
 * Interface for a router.
 *
 * @category Interfaces
 * @category Router
 */
export interface RouterInterface {
    /**
     * Runs the router.
     *
     * @param argv - The argument string.
     */
    run(argv?: string[]): void;
    /**
     * Runs the router asynchronously.
     *
     * @param argv - The argument string.
     */
    runAsync(argv?: string[]): Promise<void>;
}
