// #region Imports
import { ControllerBase } from './Abstracts/ControllerBase';
/**
 * Controller for HTML Infinite Scroll logic.
 *
 * @public
 */
export class InfiniteScrollController extends ControllerBase {
    // #region Fields
    _callback;
    _container;
    _containerElement;
    _delay;
    _disabled;
    _offset;
    _directionReversed;
    _connected;
    _scrollTimeout;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `InfiniteScrollController` class.
     *
     * @public
     */
    constructor(host, config) {
        super(host);
        this._callback = config.callback ?? (() => { });
        this._container = config.container ?? host;
        this._delay = config.delay ?? 0;
        this._disabled = config.disabled ?? false;
        this._offset = config.offset ?? 0;
        this._directionReversed = config.directionReversed ?? false;
        this._containerElement = null;
        this._scrollTimeout = null;
        this._connected = false;
        this._scrollTimeout = null;
    }
    // #endregion
    // #region Properties
    get disabled() {
        return this._disabled;
    }
    set disabled(value) {
        this._disabled = value;
    }
    get delay() {
        return this._delay;
    }
    set delay(value) {
        this._delay = value;
    }
    get offset() {
        return this._offset;
    }
    set offset(value) {
        this._offset = value;
    }
    get directionReversed() {
        return this._directionReversed;
    }
    set directionReversed(value) {
        this._directionReversed = value;
    }
    get container() {
        return this._container;
    }
    set container(value) {
        this._container = value;
    }
    // #endregion
    // #region Methods
    /**
     * Initializes the infinite scroll controller.
     *
     * @public
     */
    initialize() {
        this._containerElement = this.resolveScrollContainer();
        if (this._containerElement) {
            this._containerElement.addEventListener('scroll', (e) => this.onScroll(e), { passive: true });
            this._connected = true;
        }
    }
    /**
     * Disconnects the infinite scroll controller.
     *
     * @public
     */
    disconnect() {
        if (this._containerElement) {
            this._containerElement.removeEventListener('scroll', (e) => this.onScroll(e));
        }
        this._connected = false;
        if (this._scrollTimeout !== null) {
            clearTimeout(this._scrollTimeout);
            this._scrollTimeout = null;
        }
    }
    onScroll(event) {
        if (this._disabled)
            return;
        if (this._scrollTimeout !== null) {
            clearTimeout(this._scrollTimeout);
        }
        this._scrollTimeout = window.setTimeout(() => {
            const target = event.target;
            const height = target.scrollHeight;
            const top = target.scrollTop;
            const offsetHeight = target.offsetHeight;
            const y = top + offsetHeight + this._offset;
            if (y >= height) {
                this._callback();
            }
        }, this._delay);
    }
    resolveScrollContainer() {
        if (typeof this._container === 'string') {
            if (this._container.length > 0) {
                const queryElement = this.host.querySelector(this._container);
                if (queryElement) {
                    return queryElement;
                }
                this._connected = false;
                return null;
            }
            return null;
        }
        return this._container;
    }
}
//# sourceMappingURL=InfiniteScrollController.js.map