import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';

/**
 * Pagination component that automatically loads more rows when
 * the user scrolls down an element.
 *
 * @property {Paginable} model The model used for pagination
 * @property {String} scrollSelector The the scrollable element selector
 * @property {HTMLElement} scrollElement The scrollable element
 * @property {Number} scrollOffset The distance, in pixels, until the end that activates the loading of the next rows
 * @property {Number} maxLoads The maximum of loads that are automatically performed on scroll, 0 for no limit
 */
class Pagination extends Component {
    constructor($element, $scope) {
        super($element, $scope);
        this.scrollOffset = 500;
        this.maxLoads = 5;
        this.nLoads = 0;
        this.scrollHandler = e => this.onScroll(e);
    }

    $onInit() {
        if (!this._scrollElement)
            this.scrollElement = window;
    }

    set scrollSelector(value) {
        this._scrollSelector = value;
        this.scrollElement = document.querySelector(value);
    }

    get scrollSelector() {
        return this._scrollSelector;
    }

    set scrollElement(value) {
        if (this._scrollElement)
            this._scrollElement.removeEventListener('scroll', this.scrollHandler);

        this._scrollElement = value;

        if (value)
            this._scrollElement.addEventListener('scroll', this.scrollHandler);
    }

    get scrollElement() {
        return this._scrollElement;
    }

    onScroll() {
        let scrollInfo;
        let scrollElement = this.scrollElement;

        if (scrollElement == window) {
            scrollInfo = {
                top: window.pageYOffset,
                height: window.innerHeight,
                position: window.document.body.scrollHeight
            };
        } else {
            scrollInfo = {
                top: scrollElement.scrollTop,
                height: scrollElement.clientHeight,
                position: scrollElement.scrollHeight
            };
        }

        let shouldLoad = scrollInfo.top + scrollInfo.height >= (scrollInfo.position - this.scrollOffset)
            && !this.model.isLoading
            && (this.maxLoads <= 0 || this.nLoads < this.maxLoads);

        if (shouldLoad) {
            this.nLoads++;
            this.model.loadMore(false);
            this.$.$apply();
        }
    }

    onLoadClick() {
        if (this.maxLoads > 0 && this.nLoads == this.maxLoads)
            this.nLoads = 0;

        this.model.loadMore(false);
    }

    $onDestroy() {
        this.scrollElement = null;
    }
}

ngModule.vnComponent('vnPagination', {
    template: require('./pagination.html'),
    bindings: {
        model: '<',
        scrollSelector: '@?',
        scrollElement: '<?',
        scrollOffset: '<?',
        maxLoads: '<?'
    },
    controller: Pagination
});