// #region Imports
import { query } from '../../Controls/Directives/Query';
/**
 * A method decorator that listens to a specific event on a target element.
 *
 * @example
 * ```typescript
 * class MyElement extends HTMLElement {
 *    @Listen('click', 'self', { preventDefault: true })
 *    handleClick(event: MouseEvent) {
 *        console.log('Element clicked!', event);
 *   }
 * }
 * ```
 *
 * @public
 */
export function Listen(eventName, target = 'self', options) {
    return (prototype, methodName) => {
        const originalConnectedCallback = prototype.connectedCallback;
        const originalDisconnectedCallback = prototype.disconnectedCallback;
        const originalFirstUpdated = prototype.firstUpdated;
        // when the target is a object, we have to use a different method to get the actual target
        if (typeof target !== 'object') {
            prototype.connectedCallback = function () {
                let actualTarget = null;
                if (target === 'self') {
                    actualTarget = this;
                }
                else if (target === 'window') {
                    actualTarget = window;
                }
                else {
                    actualTarget = document;
                }
                const handler = (event) => {
                    if (options?.preventDefault) {
                        event.preventDefault();
                    }
                    this[methodName](event);
                };
                actualTarget.addEventListener(eventName, handler, options);
                if (originalConnectedCallback) {
                    originalConnectedCallback.call(this);
                }
                this[`__${methodName}_handler`] = handler;
                this[`__${methodName}_actualTarget`] = actualTarget;
            };
        }
        else {
            prototype.firstUpdated = function () {
                let actualTarget = null;
                actualTarget = query(this, target.target);
                const handler = (event) => {
                    if (options?.preventDefault) {
                        event.preventDefault();
                    }
                    this[methodName](event);
                };
                actualTarget?.addEventListener(eventName, handler, options);
                if (originalFirstUpdated) {
                    originalFirstUpdated.call(this);
                }
                this[`__${methodName}_handler`] = handler;
                this[`__${methodName}_actualTarget`] = actualTarget;
            };
        }
        prototype.disconnectedCallback = function () {
            const actualTarget = this[`__${methodName}_actualTarget`];
            actualTarget.removeEventListener(eventName, this[`__${methodName}_handler`]);
            if (originalDisconnectedCallback) {
                originalDisconnectedCallback.call(this);
            }
        };
    };
}
//# sourceMappingURL=ListenDecorator.js.map