import { EventEmitter } from 'node:events';

type SafeReturn<T, K = any> = Partial<{
    data: T;
    error: K;
}> & ({
    data: T;
    error?: never;
} | {
    data?: never;
    error: K;
});
type Result = {
    code: number;
    message: string;
};
type ResultList = Result[];
interface TorControlConfig {
    host: string;
    port: number;
    password: string | undefined;
}
/**
 * @link https://spec.torproject.org/control-spec/commands.html?highlight=SIGNAL#signal
 */
type Signal = 'RELOAD' | 'SHUTDOWN' | 'DUMP' | 'DEBUG' | 'HALT' | 'HUP' | 'INT' | 'USR1' | 'USR2' | 'TERM' | 'NEWNYM' | 'CLEARDNSCACHE' | 'HEARTBEAT' | 'ACTIVE' | 'DORMANT';

declare class TorControl extends EventEmitter {
    private _connection;
    private _config;
    private _state;
    private _debugger;
    /**
     * Get the current connection state of the TorControl
     */
    get state(): "connected" | "disconnected";
    constructor(config?: Partial<TorControlConfig>);
    private _debug;
    /**
     * Establish a connection to the TorControl
     */
    connect(): Promise<SafeReturn<boolean, Error>>;
    /**
     * Close the connection to the TorControl
     */
    disconnect(): Promise<void>;
    get disconnected(): boolean;
    /**
     * Send a command to the TorControl
     *
     * Example:
     * ```typescript
     *  const { data, error } = await torControl.sendCommand(['GETINFO', 'version']);
     *  if (error) {
     *    console.error('Error:', error);
     *    return;
     *  }
     *  console.log('GETINFO:', data); // { code: 250, message: 'version=...' }
     * ```
     *
     * @link https://spec.torproject.org/control-spec/commands.html
     * @param command
     */
    sendCommand(command: string | string[]): Promise<SafeReturn<ResultList, Error>>;
    private _solveAndPick;
    /**
     * Authenticate
     *
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=AUTHENTICATE#authenticate
     * @param password
     */
    authenticate(password: string): Promise<SafeReturn<Result, Error>>;
    /**
     * Quit
     *
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=QUIT#quit
     */
    quit(): Promise<SafeReturn<Result, Error>>;
    /**
     * Example:
     *
     * ```typescript
     * const { data, error } = await torControl.getConfig('SocksPort');
     * if (data) {
     *  console.log('SocksPort:', data); // SocksPort: 9050
     * }
     * ```
     *
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=GETCONF#getconf
     * @param key
     */
    getConfig(key: string): Promise<SafeReturn<string, Error>>;
    /**
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=SETCONF#setconf
     * @param key
     * @param value
     */
    setConfig(key: string, value: string): Promise<SafeReturn<Result, Error>>;
    /**
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=RESETCONF#resetconf
     * @param key
     */
    resetConfig(key: string): Promise<SafeReturn<Result, Error>>;
    signal(signal: Signal | string): Promise<SafeReturn<ResultList, Error>>;
    signalReload(): Promise<SafeReturn<Result, Error>>;
    signalShutdown(): Promise<SafeReturn<Result, Error>>;
    signalDump(): Promise<SafeReturn<Result, Error>>;
    signalDebug(): Promise<SafeReturn<Result, Error>>;
    signalHalt(): Promise<SafeReturn<Result, Error>>;
    signalTerm(): Promise<SafeReturn<Result, Error>>;
    signalNewNym(): Promise<SafeReturn<Result, Error>>;
    signalClearDnsCache(): Promise<SafeReturn<Result, Error>>;
    signalUsr1(): Promise<SafeReturn<Result, Error>>;
    signalUsr2(): Promise<SafeReturn<Result, Error>>;
    /**
     * Example:
     *
     * ```typescript
     * const { data, error } = await torControl.getInfo('version');
     * if (data) {
     *  console.log('Version:', data); // Version: Tor
     * }
     * ```
     *
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=GETINFO#getinfo
     * @param key
     */
    getInfo(key: string): Promise<SafeReturn<Result, Error>>;
    /**
     * Example:
     *
     * ```typescript
     * const mar = await torControl.mapAddress('1.2.3.4', 'torproject.org');
     * console.log('MAPADDRESS:', mar); // { code: 250, message: '1.2.3.4=torproject.org' }
     *
     * const gir = await torControl.getInfo('address-mappings/control');
     * console.log('GETINFO:', gir); // { code: 250, message: 'address-mappings/control=1.2.3.4 torproject.org NEVER' }
     * ```
     *
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=MAPADDRESS#mapaddress
     * @param address
     * @param target
     */
    mapAddress(address: string, target: string): Promise<SafeReturn<Result, Error>>;
    extendCircuit(circuitId: string): Promise<SafeReturn<Result, Error>>;
    /**
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=SETCIRCUITPURPOSE#setcircuitpurpose
     * @param circuitId
     * @param purpose
     */
    setCircuitPurpose(circuitId: string, purpose: string): Promise<SafeReturn<Result, Error>>;
    /**
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=SETROUTERPURPOSE#setrouterpurpose
     * @param nicknameOrKey
     * @param purpose
     */
    setRouterPurpose(nicknameOrKey: string, purpose: string): Promise<SafeReturn<Result, Error>>;
    /**
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=CLOSESTREAM#closestream
     * @param streamId
     * @param reason
     */
    setStream(streamId: string, reason: string): Promise<SafeReturn<Result, Error>>;
    /**
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=CLOSECIRCUIT#closecircuit
     * @param circuitId
     */
    closeCircuit(circuitId: string): Promise<SafeReturn<Result, Error>>;
    /**
     * @link https://spec.torproject.org/control-spec/commands.html?highlight=ATTACHSTREAM#attachstream
     * @param streamId
     * @param circuitId
     * @param hop
     */
    attachStream(streamId: string, circuitId: string, hop: number | undefined): Promise<SafeReturn<Result, Error>>;
    /**
     * Alias for `signalNewNym`
     */
    getNewIdentity(): Promise<SafeReturn<Result, Error>>;
}

export { type Result, type ResultList, type Signal, TorControl, type TorControlConfig };
