import { Observable, Subject } from "rxjs";
import { type StandardKey } from "./keys.js";
export declare enum ShortcutTypes {
    Combination = "combination",
    Sequence = "sequence"
}
interface ShortcutConfigBase {
    id: string;
    context?: string | null;
    preventDefault?: boolean;
    description?: string;
    /**
     * **Only applicable if the shortcut has no top-level `context` defined.**
     * If `true`, this shortcut is **strictly global** and will only fire when the active
     * hotkey context is `null`.
     * If `false` or `undefined` (the default), the shortcut can fire in *any* context,
     * but will be suppressed by an identical shortcut that belongs to the active context.
     * @default false
     */
    strict?: boolean;
    /**
     * The DOM element to which the event listener for this shortcut will be attached.
     * If not provided, the listener will be attached to the `document`.
     * Useful for creating shortcuts that are only active within a specific component or area.
     * @default document
     */
    target?: HTMLElement;
    /**
     * The type of keyboard event to listen for.
     * Use "keydown" for actions that should happen immediately upon pressing a key.
     * Use "keyup" for actions that should happen upon releasing a key.
     * @default "keydown"
     */
    event?: "keydown" | "keyup";
}
/**
 * Defines a single key trigger, which can be a StandardKey (for simple presses like "Escape")
 * or an object specifying the main key and its modifiers (e.g., { key: Keys.S, ctrlKey: true }).
 */
export type KeyCombinationTrigger = {
    /**
     * The main key for the combination.
     * This MUST be a value from the exported `Keys` object
     * (e.g., `Keys.A`, `Keys.Enter`, `Keys.Escape`).
     * The library handles case-insensitivity for single character keys (like A-Z, 0-9)
     * automatically when comparing with the actual browser event's `event.key`.
     * For special, multi-character keys (e.g. "ArrowUp", "Escape"), the value from
     * `Keys` ensures the correct case-sensitive string is used.
     * Refer to: https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
     */
    key: StandardKey;
    ctrlKey?: boolean;
    altKey?: boolean;
    shiftKey?: boolean;
    metaKey?: boolean;
} | StandardKey | string;
/**
 * A fully parsed, canonical representation of a single key trigger.
 * All modifier keys are explicitly defined as booleans.
 */
interface ParsedTrigger {
    key: StandardKey;
    ctrlKey: boolean;
    altKey: boolean;
    shiftKey: boolean;
    metaKey: boolean;
}
export interface KeyCombinationConfig extends ShortcutConfigBase {
    /**
     * Defines the key or key combination(s) that trigger the shortcut.
     * Can be a single trigger, an array of triggers, or a string representation.
     *
     * **Object/Array:** Each trigger can be an object specifying the main `key` (from `StandardKey`) and optional
     * modifiers (`ctrlKey`, `altKey`, `shiftKey`, `metaKey`).
     * Example: `{ key: Keys.S, ctrlKey: true }` for Ctrl+S.
     *
     * **Shorthand:** For a simple key press without modifiers, a trigger can be a `StandardKey` directly.
     * Example: `Keys.Escape` for the Escape key.
     *
     * **String:** A human-readable string like `"ctrl+s"` or `"shift+alt+k"`. Modifiers are joined by `+`.
     * Example: `"meta+k"`, `"ctrl+shift+?"`
     *
     * To define multiple triggers for the same action:
     * Example: `keys: [Keys.Enter, { key: Keys.Space, ctrlKey: true }]`
     */
    keys: KeyCombinationTrigger | KeyCombinationTrigger[];
}
export interface KeySequenceConfig extends ShortcutConfigBase {
    /**
     * An array of keys or a string defining the sequence.
     *
     * **Array:** Each key in the sequence MUST be a value from `Keys`.
     * Example: `[Keys.G, Keys.I]`
     *
     * **String:** A string where keys are separated by `->`.
     * Example: `"g -> i"`, `"up -> up -> down -> down"`
     */
    sequence: StandardKey[] | string;
    /**
     * Optional: Timeout in milliseconds between consecutive key presses in the sequence.
     * If the time between two keys in the sequence exceeds this value, the sequence attempt is reset.
     * Set to 0 or undefined to disable inter-key timeout behavior (uses simpler buffer-based matching).
     */
    sequenceTimeoutMs?: number;
}
type ShortcutConfig = KeyCombinationConfig | KeySequenceConfig;
export interface ActiveShortcut {
    id: string;
    config: ShortcutConfig;
    terminator$: Subject<void>;
    parsedTriggers?: ParsedTrigger[];
}
/**
 * Manages keyboard shortcuts for web applications.
 * Allows registration of single key combinations (e.g., Ctrl+S) and key sequences (e.g., g -> i).
 * Supports contexts to enable/disable shortcuts based on application state.
 */
export declare class Hotkeys {
    private static readonly KEYDOWN_EVENT;
    private static readonly KEYUP_EVENT;
    private static readonly LOG_PREFIX;
    private static readonly NO_OVERRIDE;
    private keydownStreams;
    private keyupStreams;
    private activeShortcuts;
    private debugMode;
    private contextStack$;
    private overrideContext$;
    /**
     * An Observable that emits the new active context name (or null) whenever it changes.
     * The active context is the override context if one is set, otherwise it's the context
     * from the top of the stack.
     */
    private readonly activeContext$;
    /**
     * Creates an instance of Hotkeys.
     * @param initialContext - Optional initial context name. This forms the base of the context stack.
     * @param debugMode - Optional. If true, debug messages will be logged to the console. Defaults to false.
     * @throws Error if not in a browser environment (i.e., `document` or `performance` is undefined).
     */
    constructor(initialContext?: string | null, debugMode?: boolean);
    /**
     * Helper method to determine the active context based on override and stack.
     */
    private _resolveActiveContext;
    private _normalizeAndParseTriggers;
    private _normalizeSequence;
    /**
     * Gets or creates a shared event stream for a given event type and target.
     * @param eventType The type of event ("keydown" or "keyup").
     * @param target The DOM element to attach the listener to.
     * @returns A shared Observable for the specified event.
     */
    private _getEventStream;
    /**
     * Sets a temporary, high-priority override context that takes precedence over the context stack.
     * @param contextName The override context to activate (can be a string or `null`).
     * @returns A `restore` function that, when called, clears the override context, reverting to the stack.
     */
    setContext(contextName: string | null): () => void;
    /**
     * @deprecated Rename to `getActiveContext`
     * Gets the current active context, considering any override.
     * @returns The current context name as a string, or `null` if no context is set.
     */
    getContext(): string | null;
    /**
     * Gets the current active context, considering any override.
     * @returns The current context name as a string, or `null` if no context is set.
     */
    getActiveContext(): string | null;
    /**
     * Pushes a new context onto the context stack. It will become active if no override context is set.
     * @param contextName The name of the context to enter (e.g., "modal", "editor").
     */
    enterContext(contextName: string | null): void;
    /**
     * Pops the current context from the stack.
     * @returns The context that was just left from the stack, or `undefined` if at the base.
     */
    leaveContext(): string | null | undefined;
    /**
     * Enables or disables debug logging for the Hotkeys instance.
     * When enabled, various internal actions and shortcut triggers will be logged to the console.
     * @param enable - True to enable debug logs, false to disable.
     */
    setDebugMode(enable: boolean): void;
    /**
     * Checks if a shortcut with the given ID is currently registered and active.
     * @param id - The unique ID of the shortcut to check.
     * @returns True if a shortcut with the specified ID exists, false otherwise.
     */
    hasShortcut(id: string): boolean;
    /**
     * An Observable that emits the new context name (or null) whenever the active context changes.
     *
     * @example
     * ```typescript
     * const hotkeys = new Hotkeys();
     * const subscription = hotkeys.onContextChange$.subscribe(newContext => {
     * console.log("Hotkey context changed to:", newContext);
     * // Update UI or perform other actions
     * });
     * // To unsubscribe when no longer needed:
     * // subscription.unsubscribe();
     * ```
     */
    get onContextChange$(): Observable<string | null>;
    /**
     * Compares two sequences of StandardKey arrays to see if they are identical.
     * @param seq1 - The first sequence array.
     * @param seq2 - The second sequence array.
     * @returns True if the sequences are identical, false otherwise.
     */
    private _areSequencesIdentical;
    /**
     * Checks if a given KeyCombinationConfig matches a given KeyboardEvent.
     * This is used internally for priority checking.
     * @param shortcutConfig The KeyCombinationConfig to check.
     * @param event The KeyboardEvent to match against.
     * @returns True if the shortcutConfig matches the event, false otherwise.
     */
    private _shortcutMatchesEvent;
    private filterByContext;
    private _registerShortcut;
    /**
     * Parses a single key trigger definition (either shorthand StandardKey or an object with modifiers)
     * into its constituent parts: main key and modifier states.
     * @param keyInput - The KeyCombinationTrigger to parse.
     * @param shortcutId - The ID of the shortcut this key trigger belongs to (for logging).
     * @returns An object containing configuredMainKey and modifier states, or null if parsing fails.
     */
    private _parseKeyTrigger;
    private _parseCombinationString;
    private _parseSequenceString;
    /**
     * Registers a key combination shortcut (e.g., Ctrl+S, Shift+Enter, or a single key like Escape)
     * and returns an Observable that emits the `KeyboardEvent` when the combination is triggered.
     * @param config - Configuration object for the key combination.
     * See {@link KeyCombinationConfig} for details.
     * @returns An `Observable<KeyboardEvent>` that you can subscribe to. The stream will be automatically
     * completed if the shortcut is removed via `remove(id)` or `destroy()`, or if it's overwritten.
     * If the configuration is invalid, an empty Observable is returned and a warning is logged.
     * @example
     * ```typescript
     * import { Keys } from "./keys";
     * // For Ctrl+S
     * const save$ = keyManager.addCombination({
     * id: "saveFile",
     * keys: { key: Keys.S, ctrlKey: true },
     * context: "editor"
     * });
     * save$.subscribe(event => console.log("File saved!", event));
     *
     * // For Ctrl+S using a string
     * const save$ = keyManager.addCombination({ id: "saveFile", keys: "ctrl+s" });
     * save$.subscribe(event => console.log("File saved!", event));
     *
     * // For just the Escape key, or Ctrl+Space
     * const close$ = keyManager.addCombination({
     * id: "closeModal",
     * keys: [Keys.Escape, {key: Keys.Space, ctrlKey: true}],
     * });
     * close$.subscribe(() => console.log("Modal closed!"));
     *
     * // For the Escape key on a specific element
     * const myModal = document.getElementById("my-modal");
     * const close$ = keyManager.addCombination({ id: "closeModal", keys: Keys.Escape, target: myModal });
     * close$.subscribe(() => console.log("Modal closed!"));
     * ```
     */
    addCombination(config: KeyCombinationConfig): Observable<KeyboardEvent>;
    /**
     * Registers a key sequence shortcut (e.g., g -> i, or ArrowUp -> ArrowUp -> ArrowDown)
     * and returns an Observable that emits the final `KeyboardEvent` of the sequence when it's completed.
     * An optional timeout can be specified for the time allowed between key presses in the sequence.
     * @param config - Configuration object for the key sequence.
     * See {@link KeySequenceConfig} for details.
     * Each key in the `sequence` array must be a value from the `Keys` object.
     * Or using string for `sequence`.
     * @returns An `Observable<KeyboardEvent>` that you can subscribe to. The stream will be automatically
     * completed if the shortcut is removed via `remove(id)` or `destroy()`, or if it's overwritten.
     * If the configuration is invalid, an empty Observable is returned and a warning is logged.
     * @example
     * ```typescript
     * import { Keys } from "./keys";
     * const konami$ = keyManager.addSequence({
     * id: "konamiCode",
     * sequence: [Keys.ArrowUp, Keys.ArrowUp, Keys.ArrowDown, Keys.ArrowDown, Keys.A, Keys.B],
     * sequenceTimeoutMs: 2000 // 2 seconds between keys
     * });
     * konami$.subscribe(event => console.log("Konami!", event));
     * ```
     * ```typescript
     * // Using a string for the sequence
     * const konami$ = keyManager.addSequence({
     * id: "konamiCode",
     * sequence: "up -> up -> down -> down -> a -> b",
     * sequenceTimeoutMs: 2000
     * });
     * konami$.subscribe(event => console.log("Konami!", event));
     * ```
     */
    addSequence(config: KeySequenceConfig): Observable<KeyboardEvent>;
    /**
     * Removes a registered shortcut by its ID.
     * This will complete the corresponding Observable stream for any subscribers.
     * @param id - The unique ID of the shortcut to remove.
     * @returns True if the shortcut was found and removed, false otherwise.
     * A warning is logged to the console if no shortcut with the given ID is found.
     */
    remove(id: string): boolean;
    /**
     * Retrieves a list of all currently active (registered) shortcut configurations.
     * This can be useful for displaying available shortcuts to the user or for debugging.
     * @returns An array of objects, where each object represents an active shortcut
     * and includes its `id`, `description` (if provided), `context` (if any),
     * and `type` (from `ShortcutTypes` enum).
     */
    getActiveShortcuts(): {
        id: string;
        description?: string;
        context?: string | null;
        type: ShortcutTypes;
    }[];
    /**
     * Cleans up all active subscriptions and resources used by the Hotkeys instance.
     * This method should be called when the Hotkeys instance is no longer needed
     * (e.g., when a component unmounts or the application is shutting down) to prevent memory leaks.
     * After calling `destroy()`, the instance should not be used further.
     */
    destroy(): void;
}
export {};
//# sourceMappingURL=hotkeys.d.ts.map