import { EventHandler, isNullOrUndefined, detach, formatUnit, getValue, addClass, select, closest } from '@syncfusion/ej2-base';
import { ListBase } from '@syncfusion/ej2-lists';
import { createElement, selectAll, } from '@syncfusion/ej2-base';
import * as CLS from '../base/classes';
var Virtualization = /** @class */ (function () {
    function Virtualization(instance) {
        this.largeIconsViewItemsCount = 40;
        this.filemanagerInstance = instance;
        this.largeIconInstance = instance.largeiconsviewModule;
    }
    // Update the scroller height based on the items count.
    Virtualization.prototype.setUlElementHeight = function () {
        this.rowItemCount = this.ValidateItemCount(Object.keys(this.largeIconInstance.allItems).length);
        this.lastRowCount = (this.largeIconInstance.allItems.length - this.largeIconsViewItemsCount) % this.rowItemCount ?
            (this.largeIconInstance.allItems.length - this.largeIconsViewItemsCount) % this.rowItemCount : this.rowItemCount;
        this.topElement = this.filemanagerInstance.createElement('div');
        this.largeIconInstance.element.firstElementChild.insertBefore(this.topElement, this.largeIconInstance.element.firstElementChild.firstChild);
        this.bottomElement = this.filemanagerInstance.createElement('div');
        this.largeIconInstance.element.firstElementChild.insertBefore(this.bottomElement, null);
        var marginValue = parseInt(window.getComputedStyle(this.largeIconInstance.itemList[0]).getPropertyValue('margin-top')) +
            parseInt(window.getComputedStyle(this.largeIconInstance.itemList[0]).getPropertyValue('margin-bottom'));
        this.listItemHeight = this.largeIconInstance.itemList[0].getBoundingClientRect().height + marginValue;
        this.totalHeight = (Object.keys(this.largeIconInstance.allItems).length / this.rowItemCount) * this.listItemHeight;
        this.topElement.style.height = 0 + 'px';
        this.bottomElement.style.height = this.totalHeight + 'px';
        this.topElementHeight = 0;
        this.bottomElementHeight = this.totalHeight;
        this.listDiff = 0;
        this.renderedCount = this.largeIconsViewItemsCount;
    };
    // Calculated the maximum number of items can be rendered in each row.
    Virtualization.prototype.ValidateItemCount = function (dataSourceLength) {
        var width = parseFloat(formatUnit(this.largeIconInstance.element.firstElementChild.clientWidth));
        var marginValue = parseInt(window.getComputedStyle(this.largeIconInstance.itemList[0]).getPropertyValue('margin-right')) +
            parseInt(window.getComputedStyle(this.largeIconInstance.itemList[0]).getPropertyValue('margin-left'));
        var itemCount = Math.floor(width / (this.largeIconInstance.itemList[0].offsetWidth + marginValue));
        if (itemCount > dataSourceLength) {
            itemCount = dataSourceLength;
        }
        return itemCount;
    };
    // Bind the scroll event for large icons view ul element.
    Virtualization.prototype.wireScrollEvent = function (destroy) {
        if (!destroy) {
            EventHandler.add(this.largeIconInstance.element.firstElementChild, 'scroll', this.onVirtualUiScroll, this);
        }
        else {
            EventHandler.remove(this.largeIconInstance.element.firstElementChild, 'scroll', this.onVirtualUiScroll);
        }
    };
    // Update the top and bottom element height and update the scroll position.
    Virtualization.prototype.onVirtualUiScroll = function (e) {
        var _a;
        var startingHeight = 0;
        this.scrollPosition = isNullOrUndefined(this.scrollPosition) ? 0 : this.scrollPosition;
        var scroll = this.getscrollerHeight(startingHeight);
        this.topElementHeight = this.listItemHeight * Math.floor(scroll / this.listItemHeight);
        this.bottomElementHeight = this.totalHeight - this.topElementHeight;
        _a = scroll <= this.totalHeight ?
            [this.topElementHeight, this.bottomElementHeight] : [this.totalHeight, 0], this.topElementHeight = _a[0], this.bottomElementHeight = _a[1];
        if (this.topElementHeight !== parseFloat(this.topElement.style.height)) {
            this.topElement.style.height = this.topElementHeight + 'px';
            this.bottomElement.style.height = this.bottomElementHeight + 'px';
            // checked whether the scrolling is upward/downward
            if (scroll > this.scrollPosition) {
                var listDiff = Math.round(((this.topElementHeight / this.listItemHeight) - this.listDiff));
                this.onNormalScroll(listDiff, true);
            }
            else {
                var listDiff = Math.round((this.listDiff - (this.topElementHeight / this.listItemHeight)));
                this.onNormalScroll(listDiff, false);
            }
        }
        this.listDiff = Math.round(this.topElementHeight / this.listItemHeight);
        this.scrollPosition = scroll;
        this.largeIconInstance.itemList = Array.prototype.slice.call(selectAll('.' + CLS.LIST_ITEM, this.largeIconInstance.element));
        this.largeIconInstance.items = this.largeIconInstance.allItems.slice(this.renderedCount -
            this.largeIconsViewItemsCount, this.renderedCount);
    };
    // Calculated the scroller height.
    Virtualization.prototype.getscrollerHeight = function (startingHeight) {
        return ((this.largeIconInstance.element.firstElementChild.scrollTop - startingHeight) <= 0) ? 0 :
            (this.largeIconInstance.element.firstElementChild.scrollTop - startingHeight);
    };
    // Update the UI based on the scrolled position.
    Virtualization.prototype.onNormalScroll = function (listDiff, isScrollingDown) {
        for (var i = 0; i < listDiff; i++) {
            this.updateUI(isScrollingDown);
        }
        this.updateSelection();
    };
    // Updating the items in large icons view dynamically.
    Virtualization.prototype.updateUI = function (isScrollingDown) {
        var _this = this;
        if (isScrollingDown) {
            this.items = this.largeIconInstance.allItems.slice(this.renderedCount, this.renderedCount + this.rowItemCount);
            if (this.items.length > 0) {
                this.listElements = ListBase.createListFromJson(createElement, this.items, this.largeIconInstance.listObj);
                this.itemList = Array.prototype.slice.call(selectAll('.' + CLS.LIST_ITEM, this.listElements));
                this.itemList.forEach(function (liEle) {
                    _this.largeIconInstance.element.firstElementChild.insertBefore(liEle, _this.bottomElement);
                });
                this.renderedCount = (this.largeIconInstance.allItems.length >= this.renderedCount + this.rowItemCount) ?
                    this.renderedCount + this.rowItemCount : this.renderedCount + this.lastRowCount;
                for (var i_1 = 0; i_1 < this.rowItemCount; i_1++) {
                    detach(this.topElement.nextElementSibling);
                }
            }
        }
        else {
            var lastItemIndex = void 0;
            var isAllRendered = void 0;
            if (this.renderedCount == this.largeIconInstance.allItems.length) {
                lastItemIndex = this.renderedCount - (this.largeIconsViewItemsCount - this.rowItemCount + this.lastRowCount);
                this.renderedCount = ((this.renderedCount - this.lastRowCount) < this.largeIconsViewItemsCount) ?
                    this.largeIconsViewItemsCount : (this.renderedCount - this.lastRowCount);
                isAllRendered = true;
            }
            else {
                lastItemIndex = this.renderedCount - this.largeIconsViewItemsCount;
                this.renderedCount = ((this.renderedCount - this.rowItemCount) < this.largeIconsViewItemsCount) ?
                    this.largeIconsViewItemsCount : (this.renderedCount - this.rowItemCount);
            }
            var startItemIndex = (lastItemIndex - this.rowItemCount > 0) ? lastItemIndex - this.rowItemCount : 0;
            this.items = this.largeIconInstance.allItems.slice(startItemIndex, lastItemIndex);
            if (this.items.length > 0) {
                this.listElements = ListBase.createListFromJson(createElement, this.items, this.largeIconInstance.listObj);
                this.itemList = Array.prototype.slice.call(selectAll('.' + CLS.LIST_ITEM, this.listElements));
                for (var len = this.itemList.length; len > 0; len--) {
                    this.largeIconInstance.element.firstElementChild.insertBefore(this.itemList[len - 1], this.topElement.nextElementSibling);
                }
                for (var i = 0; i < ((isAllRendered) ? this.lastRowCount : this.rowItemCount); i++) {
                    detach(this.bottomElement.previousElementSibling);
                }
            }
        }
    };
    // Update the selected item state.
    Virtualization.prototype.updateSelection = function () {
        for (var i = 0; i < this.filemanagerInstance.selectedItems.length; i++) {
            for (var j = 0; j < this.items.length; j++) {
                if (this.filemanagerInstance.selectedItems[i] == getValue('name', this.items[j])) {
                    this.updateCheckState(this.itemList[j]);
                }
            }
        }
    };
    // Update the check state for items.
    Virtualization.prototype.updateCheckState = function (liItem) {
        if (this.filemanagerInstance.allowMultiSelection) {
            addClass([liItem], [CLS.ACTIVE]);
            liItem.setAttribute('aria-selected', 'true');
            var checkEle = select('.' + CLS.FRAME, liItem);
            if (!checkEle.classList.contains(CLS.CHECK)) {
                addClass([checkEle], CLS.CHECK);
                closest(checkEle, '.' + CLS.CB_WRAP).setAttribute('aria-checked', 'true');
            }
        }
    };
    /**
     * For internal use only - Get the module name.
     *
     * @returns {string} - returns the module name.
     * @private
     */
    Virtualization.prototype.getModuleName = function () {
        return 'virtualization';
    };
    Virtualization.prototype.destroy = function () {
        if (this.filemanagerInstance.isDestroyed) {
            return;
        }
        if (!isNullOrUndefined(this.largeIconInstance.element.firstElementChild)) {
            this.wireScrollEvent(true);
        }
    };
    return Virtualization;
}());
export { Virtualization };
