// #region Imports
import { on } from '@breadstone/mosaik-elements';
import { ModifierKeys } from '../Types/Key';
import { ControllerBase } from './Abstracts/ControllerBase';
/**
 * @public
 */
export class KeyboardController extends ControllerBase {
    // #region Fields
    _bindings;
    _capture;
    _keydownSubscription;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `KeyEventHandler` class.
     *
     * @public
     */
    constructor(host, config) {
        super(host);
        this._capture = config?.capture ?? false;
        this._bindings = new Map(config?.entries);
        this._keydownSubscription = null;
    }
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    hostConnected() {
        this._keydownSubscription = on(this.host, 'keydown', (e) => {
            this.onKeyDown(e);
        }, { capture: this._capture });
    }
    /**
     * @public
     * @override
     */
    hostDisconnected() {
        this._keydownSubscription?.dispose();
    }
    /**
     * Adds a new key definition.
     *
     * @public
     */
    add(key, execute, canExecute, options) {
        // maybe we should handle ModifierKeys. eg. alt | ctrl | meta | shift
        (Array.isArray(key) ? key : [key]).forEach((x) => this._bindings.set(x, {
            execute: execute,
            canExecute: canExecute ?? (() => true),
            options: options
        }));
        return this;
    }
    /**
     * Removes a existing key definition.
     *
     * @public
     */
    remove(key) {
        (Array.isArray(key) ? key : [key]).forEach((x) => this._bindings.delete(x));
        return this;
    }
    /**
     * Clears all existing key definition.
     *
     * @public
     */
    clear() {
        this._bindings.clear();
        return this;
    }
    /**
     * Merges a give key definition with another.
     *
     * @public
     */
    merge(key, execute, canExecute, options) {
        (Array.isArray(key) ? key : [key]).forEach((x) => {
            if (this._bindings.has(x)) {
                const entry = this._bindings.get(x);
                this._bindings.set(x, {
                    execute: execute,
                    canExecute: canExecute ?? entry?.canExecute ?? (() => true),
                    options: options
                });
            }
            this._bindings.set(x, {
                execute: execute,
                canExecute: canExecute ?? (() => true),
                options: options
            });
        });
        return this;
    }
    /**
     * Handles a key definition.
     *
     * @public
     */
    handle(event) {
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        if (this._bindings.has(event.keyCode)) {
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            const entry = this._bindings.get(event.keyCode);
            if (entry?.options?.preventDefault) {
                event.preventDefault();
            }
            if (entry?.canExecute(event)) {
                if (entry.options?.preventDefault) {
                    // TODO: maybe we don't need it?
                    event.stopPropagation();
                }
                entry.execute(event);
            }
        }
        return false;
    }
    /**
     * Disposes all key definitions.
     *
     * @public
     */
    dispose() {
        this._bindings.clear();
    }
    /**
     * @private
     */
    extractModifierKeys(event) {
        let modeKey = ModifierKeys.None;
        if (event.altKey) {
            modeKey += ModifierKeys.Alt;
        }
        else if (event.ctrlKey) {
            modeKey += ModifierKeys.Control;
        }
        else if (event.metaKey) {
            modeKey += ModifierKeys.Meta;
        }
        else if (event.shiftKey) {
            modeKey += ModifierKeys.Shift;
        }
        return modeKey;
    }
    /**
     * @private
     */
    onKeyDown(event) {
        this.handle(event);
    }
}
//# sourceMappingURL=KeyboardController.js.map