// #region Imports
/**
 * Handles automatic scrolling when dragging near edges.
 *
 * @internal
 */
export class AutoScrollHandler {
    // #region Fields
    _config;
    _animationFrame = null;
    _velocity = { x: 0,
        y: 0 };
    _scrollContainers = [];
    // #endregion
    // #region Ctor
    /**
     * Create a new AutoScrollHandler.
     *
     * @param config - Configuration.
     */
    constructor(config) {
        this._config = this._applyDefaults(config);
    }
    // #endregion
    // #region Methods
    /**
     * Start auto-scrolling.
     *
     * @param containers - Scrollable containers.
     *
     * @public
     */
    start(containers) {
        if (!this._config.enabled) {
            return;
        }
        this._scrollContainers = containers;
    }
    /**
     * Stop auto-scrolling.
     *
     * @public
     */
    stop() {
        if (this._animationFrame !== null) {
            cancelAnimationFrame(this._animationFrame);
            this._animationFrame = null;
        }
        this._velocity = { x: 0,
            y: 0 };
        this._scrollContainers = [];
    }
    /**
     * Update auto-scroll based on pointer position.
     *
     * @param pointerPosition - Current pointer position.
     *
     * @public
     */
    update(pointerPosition) {
        if (!this._config.enabled || this._scrollContainers.length === 0) {
            return;
        }
        // Calculate scroll velocity for each container
        let needsScroll = false;
        for (const container of this._scrollContainers) {
            const rect = container.getBoundingClientRect();
            const velocity = this._calculateScrollVelocity(pointerPosition, rect);
            if (velocity.x !== 0 || velocity.y !== 0) {
                this._velocity = velocity;
                needsScroll = true;
                this._scheduleScroll(container);
                break; // Only scroll one container at a time
            }
        }
        if (!needsScroll) {
            this.stop();
        }
    }
    // #endregion
    // #region Private Methods
    /**
     * Calculate scroll velocity based on pointer proximity to edges.
     *
     * @param pointer - Pointer position.
     * @param rect - Container rect.
     * @returns Scroll velocity.
     *
     * @private
     */
    _calculateScrollVelocity(pointer, rect) {
        const threshold = this._config.threshold;
        const maxSpeed = this._config.maxSpeed;
        const velocity = { x: 0,
            y: 0 };
        // Horizontal scrolling
        const leftDist = pointer.x - rect.left;
        const rightDist = rect.right - pointer.x;
        if (leftDist < threshold) {
            // Scroll left
            velocity.x = -maxSpeed * (1 - leftDist / threshold);
        }
        else if (rightDist < threshold) {
            // Scroll right
            velocity.x = maxSpeed * (1 - rightDist / threshold);
        }
        // Vertical scrolling
        const topDist = pointer.y - rect.top;
        const bottomDist = rect.bottom - pointer.y;
        if (topDist < threshold) {
            // Scroll up
            velocity.y = -maxSpeed * (1 - topDist / threshold);
        }
        else if (bottomDist < threshold) {
            // Scroll down
            velocity.y = maxSpeed * (1 - bottomDist / threshold);
        }
        return velocity;
    }
    /**
     * Schedule scroll animation frame.
     *
     * @param container - Container to scroll.
     *
     * @private
     */
    _scheduleScroll(container) {
        if (this._animationFrame !== null) {
            return; // Already scheduled
        }
        const scroll = () => {
            if (this._velocity.x === 0 && this._velocity.y === 0) {
                this._animationFrame = null;
                return;
            }
            // Apply scroll
            container.scrollLeft += this._velocity.x;
            container.scrollTop += this._velocity.y;
            // Schedule next frame
            this._animationFrame = requestAnimationFrame(scroll);
        };
        this._animationFrame = requestAnimationFrame(scroll);
    }
    /**
     * Apply default config values.
     *
     * @param config - User config.
     * @returns Full config.
     *
     * @private
     */
    _applyDefaults(config) {
        return {
            threshold: config?.threshold ?? 50,
            maxSpeed: config?.maxSpeed ?? 10,
            enabled: config?.enabled ?? true
        };
    }
}
// #endregion
//# sourceMappingURL=AutoScrollHandler.js.map