// #region Imports
import { DomServiceLocator } from '../../Dom/Dom';
import { ControllerBase } from './Abstracts/ControllerBase';
/**
 * IntersectionAnchorController - This controller is used to observe the intersection of anchor
 * elements within a scrollable container. Supports all four directions: top, bottom, start, and end.
 *
 * @public
 */
export class IntersectionAnchorController extends ControllerBase {
    // #region Fields
    _observer;
    _anchorSelectors;
    _callback;
    _resolvedAnchors;
    // #endregion
    // #region Ctor
    constructor(host, config) {
        super(host);
        this._anchorSelectors = config.anchor ?? {};
        this._callback = config.callback;
        this._resolvedAnchors = {};
        this._observer = new IntersectionObserver((entries) => {
            this.handleChanges(entries);
            this.host.requestUpdate();
        }, {
            ...config.config,
            root: this.tryGetElement(config.target) ?? host
        });
    }
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    hostConnected() {
        this.observeAnchor('top');
        this.observeAnchor('bottom');
        this.observeAnchor('start');
        this.observeAnchor('end');
    }
    /**
     * @public
     * @override
     */
    hostDisconnected() {
        this.disconnect();
    }
    /**
     * Disconnects the IntersectionObserver and clears resolved anchors.
     *
     * @protected
     */
    disconnect() {
        this._observer.disconnect();
        this._resolvedAnchors = {};
    }
    /**
     * Handles intersection changes and maps them to the correct anchor direction.
     *
     * @param entries - The intersection observer entries.
     * @protected
     */
    handleChanges(entries) {
        const anchor = {
            isAtScrollTop: false,
            isAtScrollBottom: false,
            isAtScrollStart: false,
            isAtScrollEnd: false
        };
        for (const entry of entries) {
            if (this._resolvedAnchors.top && entry.target === this._resolvedAnchors.top) {
                anchor.isAtScrollTop = entry.isIntersecting;
            }
            if (this._resolvedAnchors.bottom && entry.target === this._resolvedAnchors.bottom) {
                anchor.isAtScrollBottom = entry.isIntersecting;
            }
            if (this._resolvedAnchors.start && entry.target === this._resolvedAnchors.start) {
                anchor.isAtScrollStart = entry.isIntersecting;
            }
            if (this._resolvedAnchors.end && entry.target === this._resolvedAnchors.end) {
                anchor.isAtScrollEnd = entry.isIntersecting;
            }
        }
        this._callback?.(anchor);
    }
    /**
     * Resolves and observes a specific anchor direction.
     *
     * @param direction - The anchor direction to observe.
     * @private
     */
    observeAnchor(direction) {
        const selector = this._anchorSelectors[direction];
        if (selector) {
            const element = this.tryGetElement(selector);
            if (element) {
                this._resolvedAnchors[direction] = element;
                this._observer.observe(element);
            }
        }
    }
    tryGetElement(elementOrSelector) {
        if (typeof elementOrSelector === 'string') {
            return DomServiceLocator.current.findDescendant(this.host, elementOrSelector);
        }
        return elementOrSelector ?? null;
    }
}
//# sourceMappingURL=IntersectionAnchorController.js.map