// #region Imports
import { ControllerBase } from '../../Controls/Controllers/Abstracts/ControllerBase';
import { createDragRef } from '../Core/DragRef';
// #endregion
// #region DragController
/**
 * Lit Reactive Controller for drag functionality.
 * Wraps DragRef to integrate with Lit components.
 *
 * @public
 */
export class DragController extends ControllerBase {
    // #region Fields
    _dragRef = null;
    _config;
    _initialized = false;
    _listeners = [];
    // #endregion
    // #region Ctor
    /**
     * Create a new DragController.
     *
     * @param host - Host component.
     * @param config - Configuration options.
     */
    constructor(host, config) {
        super(host);
        this._config = config ?? {};
    }
    // #endregion
    // #region ControllerBase Lifecycle
    /**
     * Called when the host connects to the DOM.
     *
     * @public
     * @override
     */
    hostConnected() {
        super.hostConnected();
        if (!this._initialized) {
            this._initialize();
            this._initialized = true;
        }
    }
    /**
     * Called when the host disconnects from the DOM.
     *
     * @public
     * @override
     */
    hostDisconnected() {
        super.hostDisconnected();
        this._cleanup();
    }
    // #endregion
    // #region Properties
    /**
     * Get the underlying DragRef.
     *
     * @public
     */
    get dragRef() {
        return this._dragRef;
    }
    /**
     * Get whether dragging is currently active.
     *
     * @public
     */
    get isDragging() {
        return this._dragRef?.isDragging ?? false;
    }
    /**
     * Get/set disabled state.
     *
     * @public
     */
    get disabled() {
        return this._dragRef?.disabled ?? false;
    }
    set disabled(value) {
        if (this._dragRef) {
            this._dragRef.disabled = value;
        }
    }
    /**
     * Get/set lock axis.
     *
     * @public
     */
    get lockAxis() {
        return this._dragRef?.lockAxis ?? null;
    }
    set lockAxis(value) {
        if (this._dragRef) {
            this._dragRef.lockAxis = value;
        }
    }
    /**
     * Get/set associated data.
     *
     * @public
     */
    get data() {
        return this._dragRef?.data;
    }
    set data(value) {
        if (this._dragRef) {
            this._dragRef.data = value;
        }
    }
    // #endregion
    // #region Methods
    /**
     * Update configuration.
     *
     * @param config - New configuration.
     *
     * @public
     */
    updateConfig(config) {
        this._config = {
            ...this._config,
            ...config
        };
        if (this._dragRef) {
            // Recreate DragRef with new config
            this._cleanup();
            this._initialize();
        }
    }
    /**
     * Reset drag position.
     *
     * @public
     */
    reset() {
        this._dragRef?.reset();
    }
    /**
     * Specify drag handles.
     *
     * @param handles - Handle elements.
     *
     * @public
     */
    withHandles(handles) {
        this._dragRef?.withHandles(handles);
    }
    /**
     * Specify boundary element.
     *
     * @param boundary - Boundary element or selector.
     *
     * @public
     */
    withBoundaryElement(boundary) {
        this._dragRef?.withBoundaryElement(boundary);
    }
    // #endregion
    // #region Private Methods
    /**
     * Initialize the controller.
     *
     * @private
     */
    _initialize() {
        // Create DragRef
        this._dragRef = createDragRef(this.host, this._config);
        // Set up event forwarding
        this._setupEventForwarding();
    }
    /**
     * Set up event forwarding from DragRef to host.
     *
     * @private
     */
    _setupEventForwarding() {
        if (!this._dragRef) {
            return;
        }
        // dragStart
        this._addListener('dragStart', (event) => {
            const dragEvent = event;
            this.host.dispatchEvent(new CustomEvent('dragStart', {
                bubbles: true,
                composed: true,
                cancelable: true,
                detail: {
                    ...dragEvent.detail,
                    source: this._dragRef
                }
            }));
            this.host.requestUpdate();
        });
        // dragMove
        this._addListener('dragMove', (event) => {
            const dragEvent = event;
            this.host.dispatchEvent(new CustomEvent('dragMove', {
                bubbles: true,
                composed: true,
                cancelable: false,
                detail: {
                    ...dragEvent.detail,
                    source: this._dragRef
                }
            }));
        });
        // dragRelease
        this._addListener('dragRelease', (event) => {
            const dragEvent = event;
            this.host.dispatchEvent(new CustomEvent('dragRelease', {
                bubbles: true,
                composed: true,
                cancelable: false,
                detail: {
                    ...dragEvent.detail,
                    source: this._dragRef
                }
            }));
        });
        // dragEnd
        this._addListener('dragEnd', (event) => {
            const dragEvent = event;
            this.host.dispatchEvent(new CustomEvent('dragEnd', {
                bubbles: true,
                composed: true,
                cancelable: false,
                detail: {
                    ...dragEvent.detail,
                    source: this._dragRef
                }
            }));
            this.host.requestUpdate();
        });
        // dragEnter
        this._addListener('dragEnter', (event) => {
            const dragEvent = event;
            this.host.dispatchEvent(new CustomEvent('dragEnter', {
                bubbles: true,
                composed: true,
                cancelable: false,
                detail: {
                    ...dragEvent.detail
                }
            }));
        });
        // dragExit
        this._addListener('dragExit', (event) => {
            const dragEvent = event;
            this.host.dispatchEvent(new CustomEvent('dragExit', {
                bubbles: true,
                composed: true,
                cancelable: false,
                detail: {
                    ...dragEvent.detail
                }
            }));
        });
    }
    /**
     * Add an event listener and track it for cleanup.
     *
     * @param type - Event type.
     * @param handler - Event handler.
     *
     * @private
     */
    _addListener(type, handler) {
        this._dragRef?.element.addEventListener(type, handler);
        this._listeners.push({
            type,
            handler
        });
    }
    /**
     * Cleanup resources.
     *
     * @private
     */
    _cleanup() {
        // Remove listeners
        if (this._dragRef) {
            this._listeners.forEach(({ type, handler }) => {
                if (this._dragRef) {
                    this._dragRef.element.removeEventListener(type, handler);
                }
            });
        }
        this._listeners.length = 0;
        // Dispose DragRef
        this._dragRef?.dispose();
        this._dragRef = null;
        this._initialized = false;
    }
}
// #endregion
//# sourceMappingURL=DragController.js.map