export * from './common';
import { View, ChangeType, ProxyViewContainer, Device, Observable, GridLayout, ItemSpec, GridUnitType, Utils, StackLayout, Property, booleanConverter, Label, Builder, Color, verticalAlignmentProperty } from '@nativescript/core';
import * as commonModule from './common';
Builder.knownTemplates.add('itemTemplate').add('itemSwipeTemplate').add('loadOnDemandItemTemplate').add('headerItemTemplate').add('footerItemTemplate').add('groupTemplate');
Builder.knownMultiTemplates.add('itemTemplates');
class SystemColoredStackLayout extends StackLayout {
    initNativeView() {
        this.nativeViewProtected.backgroundColor = parseInt(Device.osVersion) <= 12 ? UIColor.whiteColor : UIColor.systemBackgroundColor;
    }
}
export class ReorderHandle extends commonModule.ReorderHandle {
    constructor() {
        super();
    }
}
export class ListViewLayoutBase extends commonModule.ListViewLayoutBase {
    get ios() {
        if (!this._ios) {
            this._ios = this.getNativeLayout();
            this._ios.dynamicItemSize = this.supportsDynamicSize();
        }
        return this._ios;
    }
    supportsDynamicSize() {
        return true;
    }
    init(owner) {
        this._owner = owner;
        this.syncOwnerScrollDirection(this.scrollDirection);
    }
    reset() {
        this._owner = undefined;
    }
    getNativeLayout() {
        return undefined;
    }
    onScrollDirectionChanged(oldValue, newValue) {
        if (newValue) {
            this.ios.scrollDirection = newValue === commonModule.ListViewScrollDirection.Horizontal ? 1 /* TKListViewScrollDirection.Horizontal */ : 0 /* TKListViewScrollDirection.Vertical */;
            this.syncOwnerScrollDirection(newValue);
        }
    }
    syncOwnerScrollDirection(newScrollDirection) {
        if (this._owner === undefined) {
            return;
        }
        const owner = this._owner.get();
        owner.nativeViewProtected.scrollDirection = newScrollDirection === commonModule.ListViewScrollDirection.Horizontal ? 1 /* TKListViewScrollDirection.Horizontal */ : 0 /* TKListViewScrollDirection.Vertical */;
    }
    onItemInsertAnimationChanged(oldValue, newValue) {
        if (!newValue) {
            return;
        }
        this.ios.animationDuration = 0.5;
        switch (newValue) {
            case commonModule.ListViewItemAnimation.Fade: {
                this.ios.itemInsertAnimation = 1 /* TKListViewItemAnimation.Fade */;
                break;
            }
            case commonModule.ListViewItemAnimation.Scale: {
                this.ios.itemInsertAnimation = 2 /* TKListViewItemAnimation.Scale */;
                break;
            }
            case commonModule.ListViewItemAnimation.Slide: {
                this.ios.itemInsertAnimation = 3 /* TKListViewItemAnimation.Slide */;
                break;
            }
            default:
                this.ios.itemInsertAnimation = 0 /* TKListViewItemAnimation.Default */;
        }
    }
    onItemDeleteAnimationChanged(oldValue, newValue) {
        if (!newValue) {
            return;
        }
        this.ios.animationDuration = 0.5;
        switch (newValue) {
            case commonModule.ListViewItemAnimation.Fade: {
                this.ios.itemDeleteAnimation = 1 /* TKListViewItemAnimation.Fade */;
                break;
            }
            case commonModule.ListViewItemAnimation.Scale: {
                this.ios.itemDeleteAnimation = 2 /* TKListViewItemAnimation.Scale */;
                break;
            }
            case commonModule.ListViewItemAnimation.Slide: {
                this.ios.itemDeleteAnimation = 3 /* TKListViewItemAnimation.Slide */;
                break;
            }
            default:
                this.ios.itemDeleteAnimation = 0 /* TKListViewItemAnimation.Default */;
        }
    }
    onItemWidthChanged(oldValue, newValue) {
        this.updateIsDynamicSize();
        if (!isNaN(+newValue)) {
            this.updateItemSize();
        }
    }
    onItemHeightChanged(oldValue, newValue) {
        this.updateIsDynamicSize();
        if (!isNaN(+newValue)) {
            this.updateItemSize();
        }
    }
    updateIsDynamicSize() {
        let dynamicItemSize = this.supportsDynamicSize();
        if (this.scrollDirection === commonModule.ListViewScrollDirection.Vertical) {
            dynamicItemSize = dynamicItemSize && isNaN(this.itemHeight);
        }
        if (this.scrollDirection === commonModule.ListViewScrollDirection.Horizontal) {
            dynamicItemSize = dynamicItemSize && isNaN(this.itemWidth);
        }
        this.ios.dynamicItemSize = dynamicItemSize;
    }
    updateItemSize() {
        this.ios.itemSize = CGSizeMake(this.itemWidth ? this.itemWidth : this.ios.itemSize.width, this.itemHeight ? this.itemHeight : this.ios.itemSize.height);
    }
}
export class ListViewLinearLayout extends ListViewLayoutBase {
    constructor() {
        super(...arguments);
        this.dynamicItemSize = true;
    }
    supportsDynamicSize() {
        return this.dynamicItemSize;
    }
    getNativeLayout() {
        return TKListViewLinearLayout.new();
    }
    onDynamicItemSizePropertyChanged(oldValue, newValue) {
        this.onDynamicItemSizeChanged(oldValue, newValue);
    }
    onDynamicItemSizeChanged(oldValue, newValue) {
        this.dynamicItemSize = newValue;
    }
}
ListViewLinearLayout.dynamicItemSizeProperty = new Property({
    name: 'dynamicItemSize',
    defaultValue: true,
    valueConverter: booleanConverter,
    valueChanged: (target, oldValue, newValue) => {
        target.onDynamicItemSizePropertyChanged(oldValue, newValue);
    },
});
export class ListViewGridLayout extends ListViewLayoutBase {
    getNativeLayout() {
        return TKListViewGridLayout.new();
    }
    supportsDynamicSize() {
        return false;
    }
    onSpanCountPropertyChanged(oldValue, newValue) {
        this.onSpanCountChanged(oldValue, newValue);
    }
    onSpanCountChanged(oldValue, newValue) {
        if (!isNaN(+newValue)) {
            this.ios.spanCount = newValue;
            if (this._owner) {
                this._owner.get().refresh();
            }
        }
    }
    onLineSpacingPropertyChanged(oldValue, newValue) {
        this.onLineSpacingChanged(oldValue, newValue);
    }
    onLineSpacingChanged(oldValue, newValue) {
        if (!isNaN(+newValue)) {
            this.ios.lineSpacing = newValue;
        }
    }
}
// NOTE: this property should be defined in common module, but inheritance will not be possible then
ListViewGridLayout.spanCountProperty = new Property({
    name: 'spanCount',
    defaultValue: undefined,
    valueConverter: parseInt,
    valueChanged: (target, oldValue, newValue) => {
        target.onSpanCountPropertyChanged(oldValue, newValue);
    },
});
// NOTE: this property should be defined in common module, but inheritance will not be possible then
ListViewGridLayout.lineSpacingProperty = new Property({
    name: 'lineSpacing',
    defaultValue: undefined,
    valueConverter: parseInt,
    valueChanged: (target, oldValue, newValue) => {
        target.onLineSpacingPropertyChanged(oldValue, newValue);
    },
});
ListViewGridLayout.spanCountProperty.register(ListViewGridLayout);
ListViewGridLayout.lineSpacingProperty.register(ListViewGridLayout);
export class ListViewStaggeredLayout extends ListViewGridLayout {
    getNativeLayout() {
        const layout = TKListViewStaggeredLayout.new();
        return layout;
    }
    supportsDynamicSize() {
        return true;
    }
    updateItemSize() { }
}
var TKListViewDelegateImpl = /** @class */ (function (_super) {
    __extends(TKListViewDelegateImpl, _super);
    function TKListViewDelegateImpl() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    TKListViewDelegateImpl.initWithOwner = function (owner) {
        var instance = new TKListViewDelegateImpl();
        instance._owner = owner;
        return instance;
    };
    Object.defineProperty(TKListViewDelegateImpl.prototype, "swipeLimits", {
        get: function () {
            if (!this._swipeLimits) {
                var owner = this._owner.get();
                this._swipeLimits = owner.listViewLayout.scrollDirection === commonModule.ListViewScrollDirection.Vertical ? { left: owner.getMeasuredWidth(), top: 0, right: owner.getMeasuredWidth(), bottom: 0, threshold: 0 } : { left: 0, top: owner.getMeasuredHeight(), right: 0, bottom: owner.getMeasuredHeight(), threshold: 0 };
            }
            return this._swipeLimits;
        },
        enumerable: true,
        configurable: true
    });
    TKListViewDelegateImpl.prototype.listViewScrollViewDidScroll = function (listView, scrollView) {
        var owner = this._owner.get();
        var eventData = {
            eventName: commonModule.RadListView.scrolledEvent,
            object: owner,
            scrollOffset: owner.getScrollOffset(),
        };
        owner.notify(eventData);
    };
    TKListViewDelegateImpl.prototype.listViewScrollViewWillBeginDragging = function (listView, scrollView) {
        var owner = this._owner.get();
        var eventData = {
            eventName: commonModule.RadListView.scrollStartedEvent,
            object: owner,
            scrollOffset: owner.getScrollOffset(),
        };
        owner.notify(eventData);
    };
    TKListViewDelegateImpl.prototype.listViewScrollViewDidEndDraggingWillDecelerate = function (listView, scrollView, willDecelerate) {
        var owner = this._owner.get();
        var eventData = {
            eventName: commonModule.RadListView.scrollDragEndedEvent,
            object: owner,
            scrollOffset: owner.getScrollOffset(),
        };
        owner.notify(eventData);
        if (!willDecelerate) {
            eventData = {
                eventName: commonModule.RadListView.scrollEndedEvent,
                object: owner,
                scrollOffset: owner.getScrollOffset(),
            };
            owner.notify(eventData);
        }
    };
    TKListViewDelegateImpl.prototype.listViewScrollViewDidEndDecelerating = function (listView, scrollView) {
        var owner = this._owner.get();
        var eventData = {
            eventName: commonModule.RadListView.scrollEndedEvent,
            object: owner,
            scrollOffset: owner.getScrollOffset(),
        };
        owner.notify(eventData);
    };
    TKListViewDelegateImpl.prototype.listViewShouldHighlightItemAtIndexPath = function (listView, indexPath) {
        return true;
    };
    TKListViewDelegateImpl.prototype.listViewDidHighlightItemAtIndexPath = function (listView, indexPath) { };
    TKListViewDelegateImpl.prototype.listViewDidUnhighlightItemAtIndexPath = function (listView, indexPath) { };
    TKListViewDelegateImpl.prototype.listViewShouldSelectItemAtIndexPath = function (listView, indexPath) {
        if (!indexPath) {
            return;
        }
        var owner = this._owner.get();
        var view = owner.getViewForItem(owner.getItemAtIndex(indexPath.row));
        var args = {
            eventName: commonModule.RadListView.itemSelectingEvent,
            object: owner,
            index: owner._getIndexForIndexPath(indexPath),
            groupIndex: indexPath.section,
            returnValue: true,
            view: view,
        };
        owner.notify(args);
        return args.returnValue;
    };
    TKListViewDelegateImpl.prototype.listViewDidSelectItemAtIndexPath = function (listView, indexPath) {
        if (!indexPath) {
            return;
        }
        var owner = this._owner.get();
        var view = owner.getViewForItem(owner.getItemAtIndex(indexPath.row));
        owner._toggleSelectionColor(view, true);
        var args = {
            eventName: commonModule.RadListView.itemSelectedEvent,
            object: owner,
            index: owner._getIndexForIndexPath(indexPath),
            groupIndex: indexPath.section,
            view: view,
        };
        owner.notify(args);
    };
    TKListViewDelegateImpl.prototype.listViewDidDeselectItemAtIndexPath = function (listView, indexPath) {
        if (!indexPath) {
            return;
        }
        var owner = this._owner.get();
        var view = owner.getViewForItem(owner.getItemAtIndex(indexPath.row));
        owner._toggleSelectionColor(view, false);
        var index = owner._getIndexForIndexPath(indexPath);
        var args = {
            eventName: commonModule.RadListView.itemDeselectingEvent,
            object: owner,
            index: index,
            groupIndex: indexPath.section,
            returnValue: true,
            view: view,
        };
        owner.notify(args);
        var argsDeselected = {
            eventName: commonModule.RadListView.itemDeselectedEvent,
            object: owner,
            index: index,
            groupIndex: indexPath.section,
            view: view,
        };
        owner.notify(argsDeselected);
    };
    TKListViewDelegateImpl.prototype.listViewWillReorderItemAtIndexPath = function (listView, indexPath) {
        if (!listView || !indexPath) {
            return false;
        }
        var owner = this._owner.get();
        var view = owner.getViewForItem(owner.getItemAtIndex(indexPath.row));
        var index = owner._getIndexForIndexPath(indexPath);
        var args = {
            returnValue: true,
            eventName: commonModule.RadListView.itemReorderStartingEvent,
            object: owner,
            index: index,
            groupIndex: indexPath.section,
            view: view,
        };
        owner.notify(args);
        if (!args.returnValue) {
            return false;
        }
        args = {
            eventName: commonModule.RadListView.itemReorderStartedEvent,
            object: owner,
            index: index,
            groupIndex: indexPath.section,
            view: view,
        };
        owner.notify(args);
        return true;
    };
    TKListViewDelegateImpl.prototype.listViewDidReorderItemFromIndexPathToIndexPath = function (listView, originalIndexPath, targetIndexPath) {
        if (!listView || !originalIndexPath || !targetIndexPath) {
            return;
        }
        if (originalIndexPath.row === targetIndexPath.row) {
            return;
        }
        var owner = this._owner.get();
        owner._reorderItemInSource(originalIndexPath.row, targetIndexPath.row);
        var view = owner.getViewForItem(owner.getItemAtIndex(targetIndexPath.row));
        var args = {
            eventName: commonModule.RadListView.itemReorderedEvent,
            object: owner,
            index: owner._getIndexForIndexPath(originalIndexPath),
            groupIndex: originalIndexPath.section,
            data: { targetIndex: targetIndexPath.row, targetGroupIndex: targetIndexPath.section },
            view: view,
        };
        owner.notify(args);
    };
    TKListViewDelegateImpl.prototype.listViewShouldSwipeCellAtIndexPath = function (listView, cell, indexPath) {
        var shouldSwipe = true;
        var owner = this._owner.get();
        var index = owner._getIndexForIndexPath(indexPath);
        if (owner.hasListeners(commonModule.RadListView.itemSwipingEvent)) {
            var args = {
                eventName: commonModule.RadListView.itemSwipingEvent,
                object: owner,
                index: index,
                groupIndex: indexPath.section,
                returnValue: true,
            };
            owner.notify(args);
            shouldSwipe = args.returnValue;
        }
        if (shouldSwipe) {
            var viewAtIndex = owner._realizedCells.get(cell.tag).view;
            var startArgs = {
                eventName: commonModule.RadListView.itemSwipeProgressStartedEvent,
                object: owner,
                swipeView: viewAtIndex.itemSwipeView,
                mainView: viewAtIndex.itemView,
                index: index,
                groupIndex: indexPath.section,
                data: { swipeLimits: this.swipeLimits },
            };
            owner.notify(startArgs);
            var swipeLimits = startArgs.data.swipeLimits;
            if (swipeLimits) {
                owner.nativeViewProtected.cellSwipeLimits = UIEdgeInsetsFromString('{' + Utils.layout.toDeviceIndependentPixels(swipeLimits.top) + ', ' + Utils.layout.toDeviceIndependentPixels(swipeLimits.left) + ', ' + Utils.layout.toDeviceIndependentPixels(swipeLimits.bottom) + ', ' + Utils.layout.toDeviceIndependentPixels(swipeLimits.right) + '}');
                owner.nativeViewProtected.cellSwipeThreshold = Utils.layout.toDeviceIndependentPixels(swipeLimits.threshold);
            }
        }
        return shouldSwipe;
    };
    TKListViewDelegateImpl.prototype.listViewDidSwipeCellAtIndexPathWithOffset = function (listView, cell, indexPath, offset) {
        if (!indexPath) {
            return;
        }
        var owner = this._owner.get();
        var viewAtIndex = owner._realizedCells.get(cell.tag).view;
        var swipeOffset = { x: Utils.layout.toDevicePixels(offset.x), y: Utils.layout.toDevicePixels(offset.y), swipeLimits: this.swipeLimits };
        var args = {
            eventName: commonModule.RadListView.itemSwipeProgressChangedEvent,
            object: owner,
            swipeView: viewAtIndex.itemSwipeView,
            mainView: viewAtIndex.itemView,
            index: owner._getIndexForIndexPath(indexPath),
            groupIndex: indexPath.section,
            data: swipeOffset,
        };
        owner.notify(args);
    };
    TKListViewDelegateImpl.prototype.listViewDidFinishSwipeCellAtIndexPathWithOffset = function (listView, cell, indexPath, offset) {
        var owner = this._owner.get();
        if (!indexPath || !owner.hasListeners(commonModule.RadListView.itemSwipeProgressEndedEvent)) {
            return;
        }
        var viewAtIndex = owner._realizedCells.get(cell.tag).view;
        var swipeOffset = { x: offset.x, y: offset.y, swipeLimits: this.swipeLimits };
        var args = {
            eventName: commonModule.RadListView.itemSwipeProgressEndedEvent,
            object: owner,
            swipeView: viewAtIndex.itemSwipeView,
            mainView: viewAtIndex.itemView,
            index: owner._getIndexForIndexPath(indexPath),
            groupIndex: indexPath.section,
            data: swipeOffset,
        };
        owner.notify(args);
    };
    TKListViewDelegateImpl.prototype.listViewDidPullWithOffset = function (listView, offset) { };
    TKListViewDelegateImpl.prototype.listViewDidLongPressCellAtIndexPath = function (listView, cell, indexPath) {
        if (!indexPath) {
            return;
        }
        var owner = this._owner.get();
        var args = {
            eventName: commonModule.RadListView.itemHoldEvent,
            object: owner,
            index: owner._getIndexForIndexPath(indexPath),
            groupIndex: indexPath.section,
        };
        owner.notify(args);
    };
    TKListViewDelegateImpl.prototype.listViewShouldLoadMoreDataAtIndexPath = function (listView, indexPath) {
        if (!indexPath) {
            return false;
        }
        var owner = this._owner.get();
        var args = {
            eventName: commonModule.RadListView.loadMoreDataRequestedEvent,
            object: owner,
            index: owner._getIndexForIndexPath(indexPath),
            groupIndex: indexPath.section,
            returnValue: true,
        };
        owner.notify(args);
        return args.returnValue;
    };
    TKListViewDelegateImpl.prototype.listViewShouldRefreshOnPull = function (listView) {
        var owner = this._owner.get();
        var args = {
            eventName: commonModule.RadListView.pullToRefreshInitiatedEvent,
            object: owner,
            returnValue: true,
        };
        owner.notify(args);
        return args.returnValue;
    };
    TKListViewDelegateImpl.prototype.didReloadData = function (listView) { };
    TKListViewDelegateImpl.prototype.willInsertItemsAtIndexPaths = function (indexPaths) {
        var owner = this._owner.get();
        owner._insertingItemsWithAnimation = true;
    };
    TKListViewDelegateImpl.prototype.didInsertItems = function () {
        var owner = this._owner.get();
        owner._insertingItemsWithAnimation = false;
        if (owner._shouldDisableLoadOnDemand) {
            owner._disableLoadOnDemand();
        }
        if (owner._shouldReEnableLoadOnDemand) {
            owner._returnLoadOnDemandMode();
        }
    };
    TKListViewDelegateImpl.prototype.willDisplayCellForItemAtIndexPath = function (cell, indexPath) {
        var _a;
        (_a = this._owner.get()) === null || _a === void 0 ? void 0 : _a.showCell(cell, indexPath);
    };
    TKListViewDelegateImpl.prototype.didEndDisplayingAtIndexPathsCell = function (indexPath, cell) {
        var _a;
        (_a = this._owner.get()) === null || _a === void 0 ? void 0 : _a.hideCell(cell, indexPath);
    };
    TKListViewDelegateImpl.ObjCProtocols = [TKListViewDelegate];
    return TKListViewDelegateImpl;
}(NSObject));
var TKListViewDataSourceImpl = /** @class */ (function (_super) {
    __extends(TKListViewDataSourceImpl, _super);
    function TKListViewDataSourceImpl() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    TKListViewDataSourceImpl.initWithOwner = function (owner) {
        var instance = new TKListViewDataSourceImpl();
        instance._owner = owner;
        if (instance._owner.get().isDataOperationsEnabled) {
            instance.initDataOperationsSource();
        }
        return instance;
    };
    TKListViewDataSourceImpl.prototype.initDataOperationsSource = function () {
        var listView = this._owner.get();
        if (!listView.items) {
            return;
        }
        var myArray = [];
        listView.items.forEach(function (element) {
            myArray.push(element);
        });
        this.nativeTKDataSource = TKRLVDataSource.alloc().initWithItemSource(myArray);
        if (listView.groupingFunction) {
            this.nativeTKDataSource.addGroupDescriptor(TKDataSourceGroupDescriptor.alloc().initWithBlock(listView.groupingFunction));
        }
        else {
            this.nativeTKDataSource.addGroupDescriptor(TKDataSourceGroupDescriptor.alloc().initWithBlock(this.defaultGroupingFunction));
        }
        if (listView.filteringFunction) {
            this.nativeTKDataSource.addFilterDescriptor(TKDataSourceFilterDescriptor.alloc().initWithBlock(listView.filteringFunction));
        }
        if (listView.sortingFunction) {
            this.nativeTKDataSource.addSortDescriptor(TKDataSourceSortDescriptor.alloc().initWithComparator(listView.sortingFunction));
        }
        this.nativeTKDataSource.reloadData();
    };
    TKListViewDataSourceImpl.prototype.listViewNumberOfItemsInSection = function (listView, section) {
        var ownerListView = this._owner.get();
        var result = 0;
        if (!ownerListView.isDataOperationsEnabled) {
            result = ownerListView.items ? ownerListView.items.length : 0;
        }
        else {
            if (!this.nativeTKDataSource || this.nativeTKDataSource.items.count === 0) {
                return 0;
            }
            var groupItem = this.nativeTKDataSource.items[section];
            result = groupItem.items && this.nativeTKDataSource.items.count ? groupItem.items.count : this.nativeTKDataSource.itemSource.length;
        }
        return result;
    };
    TKListViewDataSourceImpl.prototype.listViewCellForItemAtIndexPathIsInitial = function (listView, indexPath, isInitial) {
        var owner = this._owner.get();
        owner._preparingCell = true;
        var loadOnDemandCell = listView.dequeueLoadOnDemandCellForIndexPath(indexPath);
        if (loadOnDemandCell) {
            if (owner.loadOnDemandItemTemplate || owner.itemViewLoader) {
                owner.prepareLoadOnDemandCell(loadOnDemandCell, indexPath);
            }
            loadOnDemandCell.backgroundView.stroke = null;
            owner._preparingCell = false;
            return loadOnDemandCell;
        }
        var templateType = this._owner.get()._getItemTemplateType(indexPath);
        var cell = listView.dequeueReusableCellWithReuseIdentifierForIndexPath(templateType, indexPath);
        if (owner.itemSelectedBackgroundColor && cell && cell.selectedBackgroundView) {
            if (owner.multipleSelection) {
                cell.selectedBackgroundView.checkViewFillColor = owner.itemSelectedBackgroundColor.ios;
                cell.selectedBackgroundView.updateCheckViewForSelection();
            }
            else {
                cell.selectedBackgroundView.backgroundColor = owner.itemSelectedBackgroundColor.ios;
            }
        }
        if (!cell.view) {
            cell.backgroundView.stroke = null;
            cell.selectedBackgroundView.stroke = null;
            cell.offsetContentViewInMultipleSelection = false;
        }
        owner.prepareCell(cell, indexPath, templateType, !isInitial);
        owner._preparingCell = false;
        return cell;
    };
    TKListViewDataSourceImpl.prototype.numberOfSectionsInListView = function (listView) {
        var owner = this._owner.get();
        var result = 0;
        if (!owner.isDataOperationsEnabled) {
            result = 1;
        }
        else {
            if (!this.nativeTKDataSource) {
                return;
            }
            result = this.nativeTKDataSource.items && this.nativeTKDataSource.items.count ? this.nativeTKDataSource.items.count : 1;
        }
        // TODO: call event handler from public interface
        return result;
    };
    TKListViewDataSourceImpl.prototype.listViewViewForSupplementaryElementOfKindAtIndexPath = function (listView, kind, indexPath) {
        var owner = this._owner.get();
        var cell;
        if (kind === 'header' && (owner.headerItemTemplate !== undefined || owner.groupingFunction || owner.itemViewLoader !== undefined)) {
            cell = listView.dequeueReusableSupplementaryViewOfKindWithReuseIdentifierForIndexPath(kind, NSString.stringWithCString('header'), indexPath);
            owner._preparingCell = true;
            owner.prepareHeaderCell(cell, indexPath);
            owner._preparingCell = false;
        }
        else if (kind === 'footer' && (owner.footerItemTemplate !== undefined || owner.itemViewLoader !== undefined)) {
            cell = listView.dequeueReusableSupplementaryViewOfKindWithReuseIdentifierForIndexPath(kind, NSString.stringWithCString('footer'), indexPath);
            owner._preparingCell = true;
            owner.prepareFooterCell(cell, indexPath);
            owner._preparingCell = false;
        }
        return cell;
    };
    TKListViewDataSourceImpl.prototype.defaultGroupingFunction = function () {
        return function (item) {
            return item;
        };
    };
    TKListViewDataSourceImpl.ObjCProtocols = [TKListViewDataSource];
    return TKListViewDataSourceImpl;
}(NSObject));
var ExtendedHeaderCell = /** @class */ (function (_super) {
    __extends(ExtendedHeaderCell, _super);
    function ExtendedHeaderCell() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    ExtendedHeaderCell.new = function () {
        var instance = _super.new.call(this);
        return instance;
    };
    ExtendedHeaderCell.class = function () {
        return ExtendedHeaderCell;
    };
    Object.defineProperty(ExtendedHeaderCell.prototype, "view", {
        get: function () {
            return this._view;
        },
        set: function (value) {
            this._view = value;
        },
        enumerable: true,
        configurable: true
    });
    ExtendedHeaderCell.prototype.getCellPreferredNativeSize = function (targetSize) {
        if (this.view && this.view.parent) {
            var listView = this.view.parent;
            listView._preparingCell = true;
            var dimensions = listView.layoutHeaderFooterCell(this);
            listView._preparingCell = false;
            return CGSizeMake(Utils.layout.toDeviceIndependentPixels(dimensions.measuredWidth), Utils.layout.toDeviceIndependentPixels(dimensions.measuredHeight));
        }
        return targetSize;
    };
    ExtendedHeaderCell.prototype.systemLayoutSizeFittingSize = function (targetSize) {
        return this.getCellPreferredNativeSize(targetSize);
    };
    ExtendedHeaderCell.prototype.systemLayoutSizeFittingSizeWithHorizontalFittingPriorityVerticalFittingPriority = function (targetSize, horizontalFittingPriority, verticalFittingPriority) {
        return this.getCellPreferredNativeSize(targetSize);
    };
    return ExtendedHeaderCell;
}(TKListViewHeaderCell));
var ExtendedFooterCell = /** @class */ (function (_super) {
    __extends(ExtendedFooterCell, _super);
    function ExtendedFooterCell() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    ExtendedFooterCell.new = function () {
        var instance = _super.new.call(this);
        return instance;
    };
    ExtendedFooterCell.class = function () {
        return ExtendedFooterCell;
    };
    Object.defineProperty(ExtendedFooterCell.prototype, "view", {
        get: function () {
            return this._view;
        },
        set: function (value) {
            this._view = value;
        },
        enumerable: true,
        configurable: true
    });
    ExtendedFooterCell.prototype.getCellPreferredNativeSize = function (targetSize) {
        if (this.view && this.view.parent) {
            var listView = this.view.parent;
            listView._preparingCell = true;
            var dimensions = listView.layoutHeaderFooterCell(this);
            listView._preparingCell = false;
            return CGSizeMake(Utils.layout.toDeviceIndependentPixels(dimensions.measuredWidth), Utils.layout.toDeviceIndependentPixels(dimensions.measuredHeight));
        }
        return targetSize;
    };
    ExtendedFooterCell.prototype.systemLayoutSizeFittingSize = function (targetSize) {
        return this.getCellPreferredNativeSize(targetSize);
    };
    ExtendedFooterCell.prototype.systemLayoutSizeFittingSizeWithHorizontalFittingPriorityVerticalFittingPriority = function (targetSize, horizontalFittingPriority, verticalFittingPriority) {
        return this.getCellPreferredNativeSize(targetSize);
    };
    return ExtendedFooterCell;
}(TKListViewFooterCell));
var ExtendedLoadOnDemandCell = /** @class */ (function (_super) {
    __extends(ExtendedLoadOnDemandCell, _super);
    function ExtendedLoadOnDemandCell() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    ExtendedLoadOnDemandCell.new = function () {
        var instance = _super.new.call(this);
        return instance;
    };
    ExtendedLoadOnDemandCell.class = function () {
        return ExtendedLoadOnDemandCell;
    };
    ExtendedLoadOnDemandCell.prototype.systemLayoutSizeFittingSize = function (targetSize) {
        if (this.view && this.view.parent) {
            return CGSizeMake(Utils.layout.toDeviceIndependentPixels(this.view.getMeasuredWidth()), Utils.layout.toDeviceIndependentPixels(this.view.getMeasuredHeight()));
        }
        // On iOS the default view doesn't have a size explicitly set so
        // we restrict it here so that it doesn't occupy the whole screen.
        return CGSizeMake(targetSize.width, 44);
    };
    ExtendedLoadOnDemandCell.prototype.willMoveToSuperview = function (newSuperview) {
        var parent = (this.view ? this.view.parent : null);
        // When inside ListView and there is no newSuperview this cell is
        // removed from native visual tree so we remove it from our tree too.
        if (parent && !newSuperview) {
            parent._removeView(this.view);
        }
    };
    Object.defineProperty(ExtendedLoadOnDemandCell.prototype, "view", {
        get: function () {
            return this._view;
        },
        set: function (value) {
            this._view = value;
        },
        enumerable: true,
        configurable: true
    });
    return ExtendedLoadOnDemandCell;
}(TKListViewLoadOnDemandCell));
var ExtendedListViewCell = /** @class */ (function (_super) {
    __extends(ExtendedListViewCell, _super);
    function ExtendedListViewCell() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.touchStarted = false;
        return _this;
    }
    ExtendedListViewCell.new = function () {
        var instance = _super.new.call(this);
        return instance;
    };
    ExtendedListViewCell.class = function () {
        return ExtendedListViewCell;
    };
    ExtendedListViewCell.prototype.willMoveToSuperview = function (newSuperview) {
        var parent = (this.view && this.view.itemView ? this.view.itemView.parent : null);
        // When inside ListView and there is no newSuperview this cell is
        // removed from native visual tree so we remove it from our tree too.
        if (parent && !newSuperview) {
            parent._removeContainer(this);
        }
    };
    ExtendedListViewCell.prototype.getCellPreferredNativeSize = function (targetSize) {
        if (this.view && this.view.itemView && this.view.itemView.parent) {
            var owner = this.view.itemView.parent;
            owner._preparingCell = true;
            var dimensions = owner.layoutCell(this, undefined);
            owner._preparingCell = false;
            return CGSizeMake(Utils.layout.toDeviceIndependentPixels(dimensions.measuredWidth), Utils.layout.toDeviceIndependentPixels(dimensions.measuredHeight));
        }
        return targetSize;
    };
    ExtendedListViewCell.prototype.systemLayoutSizeFittingSize = function (targetSize) {
        return this.getCellPreferredNativeSize(targetSize);
    };
    ExtendedListViewCell.prototype.systemLayoutSizeFittingSizeWithHorizontalFittingPriorityVerticalFittingPriority = function (targetSize, horizontalFittingPriority, verticalFittingPriority) {
        return this.getCellPreferredNativeSize(targetSize);
    };
    // This shows in the profiling. Can it be avoided?
    ExtendedListViewCell.prototype.touchesBeganWithEvent = function (touches, event) {
        _super.prototype.touchesBeganWithEvent.call(this, touches, event);
        if (touches.count !== 1) {
            this.touchStarted = false;
            return;
        }
        this.touchStarted = true;
    };
    // This shows in the profiling. Can it be avoided?
    ExtendedListViewCell.prototype.touchesMovedWithEvent = function (touches, event) {
        _super.prototype.touchesMovedWithEvent.call(this, touches, event);
        this.touchStarted = false;
    };
    ExtendedListViewCell.prototype.touchesEndedWithEvent = function (touches, event) {
        if (touches.count === 1 && this.touchStarted === true && this.view && this.view.itemView && this.view.itemView.parent) {
            var owner = this.view.itemView.parent;
            var allObjects = touches.allObjects;
            var touchEvent = allObjects.objectAtIndex(0);
            var currentIndexPath = owner.nativeViewProtected.indexPathForCell(this);
            // currentIndexPath can be null if just after clicking
            // in a cell the list is scrolled so when the event ended
            // when the tapped cell is not visible anymore, so indexPathForCell
            // does not find the cell
            // TODO: find a more elegant fix than this workaround
            if (currentIndexPath && touchEvent.tapCount === 1) {
                if (owner.hasListeners(commonModule.RadListView.itemTapEvent)) {
                    var args = {
                        ios: touches,
                        eventName: commonModule.RadListView.itemTapEvent,
                        object: owner,
                        view: this.myContentView,
                        index: owner._getIndexForIndexPath(currentIndexPath),
                        groupIndex: currentIndexPath.section,
                    };
                    owner.notify(args);
                }
            }
        }
        _super.prototype.touchesEndedWithEvent.call(this, touches, event);
    };
    ExtendedListViewCell.prototype.getCurrentIndexPath = function () {
        if (this.view && this.view.itemView && this.view.itemView.parent) {
            var owner = this.view.itemView.parent;
            return owner.nativeViewProtected.indexPathForCell(this);
        }
        else {
            return NSIndexPath.indexPathWithIndex(0);
        }
    };
    return ExtendedListViewCell;
}(TKListViewCell));
/////////////////////////////////////////////////////////////
// ListView
export class RadListView extends commonModule.RadListView {
    constructor() {
        super();
        this._realizedCells = new Map();
        this._nextCellTag = 0;
        this.on('bindingContextChange', this.bindingContextChanged, this);
        this.listViewLayout = new ListViewLinearLayout();
        this._heights = new Array();
    }
    reloadDataSource() {
        this._dataSource = TKListViewDataSourceImpl.initWithOwner(new WeakRef(this));
        this.nativeViewProtected.dataSource = this._dataSource;
    }
    createNativeView() {
        return TKListView.new();
    }
    initNativeView() {
        const nativeView = this.nativeViewProtected;
        this._delegate = TKListViewDelegateImpl.initWithOwner(new WeakRef(this));
        this.reloadDataSource();
        nativeView.autoresizingMask = 2 /* UIViewAutoresizing.FlexibleWidth */ | 16 /* UIViewAutoresizing.FlexibleHeight */;
        nativeView.cellSwipeThreshold = 30; // the threshold after which the cell will auto swipe to the end and will not jump back to the center.
        nativeView.registerClassForCellWithReuseIdentifier(ExtendedListViewCell.class(), this._defaultTemplate.key);
        nativeView.registerClassForSupplementaryViewOfKindWithReuseIdentifier(ExtendedHeaderCell.class(), TKListViewElementKindSectionHeader, NSString.stringWithCString('header'));
        nativeView.registerClassForSupplementaryViewOfKindWithReuseIdentifier(ExtendedFooterCell.class(), TKListViewElementKindSectionFooter, NSString.stringWithCString('footer'));
        nativeView.registerLoadOnDemandCell(ExtendedLoadOnDemandCell.class());
        this.syncItemTemplates();
        this.syncCellReorder();
        this.syncCellSwipe();
        this.syncLoadOnDemandBufferSize();
        this.syncLoadOnDemandMode();
        this.syncPullToRefresh();
        this.syncSelection();
        this.syncSelectionBehavior();
        this.syncReorderMode();
        this.syncListViewLayout(this.listViewLayout);
    }
    disposeNativeView() {
        this.nativeViewProtected.dataSource = null;
        this.clearEmbeddedViews();
        super.disposeNativeView();
    }
    setHeightForCell(index, value) {
        this._heights[index] = value;
    }
    selectAll() {
        super.selectAll();
        for (let i = 0; i < this.items.length; i++) {
            const indexPathToSelect = NSIndexPath.indexPathForRowInSection(i, 0);
            this.nativeViewProtected.selectItemAtIndexPathAnimatedScrollPosition(indexPathToSelect, false, 0 /* UICollectionViewScrollPosition.None */);
        }
    }
    deselectAll() {
        for (let i = 0; i < this.items.length; i++) {
            const indexPathToSelect = NSIndexPath.indexPathForRowInSection(i, 0);
            this.nativeViewProtected.deselectItemAtIndexPathAnimated(indexPathToSelect, false);
        }
    }
    isItemSelected(item) {
        const indexOfTargetItem = this.items.indexOf(item);
        const selectedIndexPaths = this.nativeViewProtected.indexPathsForSelectedItems;
        for (let i = 0; i < selectedIndexPaths.count; i++) {
            const indexPath = selectedIndexPaths.objectAtIndex(i);
            if (indexOfTargetItem === indexPath.row) {
                return true;
            }
        }
        return false;
    }
    selectItemAt(index) {
        const indexPathToSelect = NSIndexPath.indexPathForRowInSection(index, 0);
        this.nativeViewProtected.selectItemAtIndexPathAnimatedScrollPosition(indexPathToSelect, false, 0 /* UICollectionViewScrollPosition.None */);
    }
    deselectItemAt(index) {
        const indexPathToSelect = NSIndexPath.indexPathForRowInSection(index, 0);
        this.nativeViewProtected.deselectItemAtIndexPathAnimated(indexPathToSelect, false);
    }
    getViewForItem(item) {
        let result = undefined;
        if (item) {
            this._realizedCells.forEach(function (value, key) {
                if (value && value.view) {
                    const cellItemView = value.view.itemView;
                    if (cellItemView && cellItemView.bindingContext === item) {
                        result = cellItemView;
                    }
                }
            }, this);
        }
        return result;
    }
    getSelectedItems() {
        const selectedIndexPaths = this.nativeViewProtected.indexPathsForSelectedItems;
        const result = new Array();
        for (let i = 0; i < selectedIndexPaths.count; i++) {
            const indexPath = selectedIndexPaths.objectAtIndex(i);
            const itemCell = indexPath && this.nativeViewProtected.cellForItemAtIndexPath(indexPath);
            const bindingContext = itemCell && itemCell.view && itemCell.view.itemView && itemCell.view.itemView.bindingContext;
            result.push(bindingContext ? bindingContext : this.getItemAtIndex(indexPath.row));
        }
        return result;
    }
    bindingContextChanged(data) {
        // We need this to calculate the header-footer size based on bindings to the context.
        if (data.value !== undefined) {
            this.updateHeaderFooter();
        }
    }
    updateHeaderFooter() {
        if (this.nativeViewProtected && this.nativeViewProtected.layout) {
            const scrollDirection = this.listViewLayout.scrollDirection;
            const sizeRestriction = {
                width: scrollDirection === commonModule.ListViewScrollDirection.Vertical ? this.getMeasuredWidth() : undefined,
                height: scrollDirection === commonModule.ListViewScrollDirection.Vertical ? undefined : this.getMeasuredHeight(),
            };
            const groupTempView = this.getViewForViewType(commonModule.ListViewViewType.GroupView);
            let tempView = groupTempView != null && this.isDataOperationsEnabled ? groupTempView : this.getViewForViewType(commonModule.ListViewViewType.HeaderView);
            if (tempView) {
                this.disableIosOverflowSafeArea(tempView);
                this._addView(tempView);
                tempView.bindingContext = this.bindingContext;
                const measuredSize = this.measureCell(tempView, sizeRestriction);
                this.nativeViewProtected.layout.headerReferenceSize = CGSizeMake(Utils.layout.toDeviceIndependentPixels(measuredSize.measuredWidth), Utils.layout.toDeviceIndependentPixels(measuredSize.measuredHeight));
                this._removeView(tempView);
            }
            else {
                this.nativeViewProtected.layout.headerReferenceSize = CGSizeMake(0, 0);
            }
            tempView = this.getViewForViewType(commonModule.ListViewViewType.FooterView);
            if (tempView) {
                this.disableIosOverflowSafeArea(tempView);
                this._addView(tempView);
                tempView.bindingContext = this.bindingContext;
                const measuredSize = this.measureCell(tempView, sizeRestriction);
                this.nativeViewProtected.layout.footerReferenceSize = CGSizeMake(Utils.layout.toDeviceIndependentPixels(measuredSize.measuredWidth), Utils.layout.toDeviceIndependentPixels(measuredSize.measuredHeight));
                this._removeView(tempView);
            }
            else {
                this.nativeViewProtected.layout.footerReferenceSize = CGSizeMake(0, 0);
            }
            this.refresh();
        }
    }
    _getDefaultGroupContent() {
        const parentStack = new SystemColoredStackLayout();
        const lbl = new Label();
        lbl.bind({
            targetProperty: 'text',
            sourceProperty: '$value.category',
        });
        lbl.height = 50;
        lbl.padding = 15;
        parentStack.addChild(lbl);
        return parentStack;
    }
    onReorderModeChanged(oldValue, newValue) {
        this.syncReorderMode();
    }
    onListViewLayoutChanged(oldValue, newValue) {
        if (newValue && newValue instanceof ListViewGridLayout && !newValue.itemHeight) {
            console.log("Warning: When using 'listViewLayout' of type ListViewGridLayout it is recommended to set it's 'itemHeight' property.");
        }
        if (oldValue) {
            oldValue.reset();
        }
        this.syncListViewLayout(newValue);
    }
    onItemTemplateSelectorChanged(oldValue, newValue) {
        super.onItemTemplateSelectorChanged(oldValue, newValue);
        this.refresh();
    }
    syncListViewLayout(newValue) {
        const newLayout = newValue;
        if (newLayout && this.nativeViewProtected) {
            this.nativeViewProtected.layout = newValue.ios;
            this.refresh();
            newLayout.init(new WeakRef(this));
            this.updateHeaderFooter();
            this.nativeViewProtected.cellSwipeLimits = newLayout.scrollDirection === commonModule.ListViewScrollDirection.Horizontal ? UIEdgeInsetsFromString('{60, 0, 60, 0}') : UIEdgeInsetsFromString('{0, 60, 0, 60}');
        }
    }
    clearRealizedCells() {
        this._realizedCells.forEach((value, key) => {
            this._clearCellViews(value);
            this._removeContainer(value);
        });
        this._realizedCells.clear();
        this._nextCellTag = 0;
    }
    _removeContainer(cell) {
        if (cell && cell.view) {
            if (cell.view.itemView) {
                this._removeView(cell.view.itemView);
            }
            if (cell.view.itemSwipeView) {
                this._removeView(cell.view.itemSwipeView);
            }
            if (cell.view.parent) {
                cell.view.parent._removeView(cell.view);
            }
            if (this._realizedCells.get(cell.tag)) {
                this._realizedCells.delete(cell.tag);
            }
            cell.selectedBackgroundView = undefined;
            cell.backgroundView = undefined;
            cell.myBackgroundView = undefined;
            cell.view = undefined;
            cell.myContentView = undefined;
            cell.itemViewMeasuredSize = undefined;
            cell.swipeViewMeasuredSize = undefined;
        }
    }
    _toggleSelectionColor(view, isSelected) {
        if (!view) {
            return;
        }
        if (isSelected) {
            view.backgroundColor = new Color('transparent');
        }
        else if (view.backgroundColor && view.backgroundColor.toString() === new Color('transparent').toString()) {
            view.backgroundColor = view['nsMainBackgroundColor'];
        }
    }
    _clearCellViews(cell) {
        if (cell && cell.view) {
            if (cell.view.itemView && cell.view.itemView.nativeViewProtected) {
                cell.view.itemView.nativeViewProtected.removeFromSuperview();
            }
            if (cell.view.itemSwipeView && cell.view.itemSwipeView.nativeViewProtected) {
                cell.view.itemSwipeView.nativeViewProtected.removeFromSuperview();
            }
            if (cell.view.nativeViewProtected) {
                cell.view.nativeViewProtected.removeFromSuperview();
            }
        }
    }
    onItemTemplateChanged(oldValue, newValue) {
        if (!newValue) {
            return;
        }
        this.refresh();
    }
    onGroupTemplateChanged(oldValue, newValue) {
        super.onGroupTemplateChanged(oldValue, newValue);
        this.clearCellsAndUpdateHeaderFooter();
    }
    onItemTemplatesChanged(oldValue, newValue) {
        super.onItemTemplatesChanged(oldValue, newValue);
        this.syncItemTemplates();
    }
    onLoadOnDemandItemTemplateChanged(oldValue, newValue) {
        if (!newValue || !this.nativeViewProtected) {
            return;
        }
        if (this._loadOnDemandModeInternal === commonModule.ListViewLoadOnDemandMode.Auto) {
            const loadOnDemandView = this.getViewForViewType(commonModule.ListViewViewType.LoadOnDemandView);
            if (loadOnDemandView) {
                this.nativeViewProtected.loadOnDemandView = loadOnDemandView.ios;
            }
        }
        this.refresh();
    }
    onItemSwipeTemplateChanged(oldValue, newValue) {
        if (!newValue) {
            return;
        }
        this.refresh();
    }
    onMultipleSelectionChanged(oldValue, newValue) {
        this.syncSelection();
    }
    onHeaderItemTemplateChanged(oldValue, newValue) {
        super.onHeaderItemTemplateChanged(oldValue, newValue);
        this.clearCellsAndUpdateHeaderFooter();
    }
    onFooterItemTemplateChanged(oldValue, newValue) {
        super.onFooterItemTemplateChanged(oldValue, newValue);
        this.clearCellsAndUpdateHeaderFooter();
    }
    onEnableCollapsibleGroupsChanged(oldValue, newValue) {
        console.log("Warning: The 'Collapsible Groups' feature is not supported on iOS");
    }
    onItemSelectedBackgroundColorChanged(oldValue, newValue) {
        this.refresh();
    }
    onGroupingFunctionChanged(oldValue, newValue) {
        super.onGroupingFunctionChanged(oldValue, newValue);
        this.clearCellsAndUpdateHeaderFooter();
    }
    onFilteringFunctionChanged(oldValue, newValue) {
        this.refresh();
    }
    onSortingFunctionChanged(oldValue, newValue) {
        this.refresh();
    }
    syncReorderMode() {
        if (!this.nativeViewProtected) {
            return;
        }
        if (this.reorderMode && this.reorderMode === commonModule.ListViewReorderMode.Drag) {
            this.nativeViewProtected.reorderMode = 0 /* TKListViewReorderMode.WithHandle */;
        }
        else if (this.reorderMode && this.reorderMode === commonModule.ListViewReorderMode.HoldAndDrag) {
            this.nativeViewProtected.reorderMode = 1 /* TKListViewReorderMode.WithLongPress */;
        }
        this.refresh();
    }
    isSwipeEnabled() {
        return this.itemSwipe || this.swipeActions;
    }
    syncItemTemplates() {
        if (this.nativeViewProtected) {
            for (let i = 0, length = this._itemTemplatesInternal.length; i < length; i++) {
                this.nativeViewProtected.registerClassForCellWithReuseIdentifier(ExtendedListViewCell.class(), this._itemTemplatesInternal[i].key.toLowerCase());
            }
        }
    }
    syncSelection() {
        if (this.nativeViewProtected) {
            this.nativeViewProtected.allowsMultipleSelection = this.multipleSelection ? true : false;
        }
    }
    onItemReorderChanged(oldValue, newValue) {
        this.syncCellReorder();
    }
    syncCellReorder() {
        if (this.nativeViewProtected) {
            this.nativeViewProtected.allowsCellReorder = this.itemReorder ? true : false;
        }
    }
    clearCellsAndUpdateHeaderFooter() {
        this.clearEmbeddedViews();
        this.updateHeaderFooter();
    }
    onItemSwipeChanged(oldValue, newValue) {
        super.onItemSwipeChanged(oldValue, newValue);
        this.syncCellSwipe();
    }
    onSwipeActionsChanged(oldValue, newValue) {
        super.onSwipeActionsChanged(oldValue, newValue);
        this.syncCellSwipe();
    }
    syncCellSwipe() {
        if (this.nativeViewProtected) {
            this.nativeViewProtected.allowsCellSwipe = this.isSwipeEnabled() ? true : false;
        }
    }
    onPullToRefreshChanged(oldValue, newValue) {
        this.syncPullToRefresh();
    }
    syncPullToRefresh() {
        if (this.nativeViewProtected) {
            this.nativeViewProtected.allowsPullToRefresh = this.pullToRefresh ? true : false;
            const style = this.pullToRefreshStyle;
            if (style) {
                if (style.indicatorColor) {
                    this.nativeViewProtected.pullToRefreshView.activityIndicator.color = style.indicatorColor.ios;
                }
                if (style.indicatorBackgroundColor) {
                    this.nativeViewProtected.pullToRefreshView.activityIndicator.backgroundColor = style.indicatorBackgroundColor.ios;
                    this.nativeViewProtected.pullToRefreshView.backgroundColor = style.indicatorBackgroundColor.ios;
                }
            }
        }
    }
    onPullToRefreshStyleChanged(oldValue, newValue) {
        this.syncPullToRefresh();
    }
    onLoadOnDemandModeChanged(oldValue, newValue) {
        this.setLoadOnDemandModeInternal(newValue);
    }
    setLoadOnDemandModeInternal(value) {
        this._loadOnDemandModeInternal = value;
        this.syncLoadOnDemandMode();
    }
    syncLoadOnDemandMode() {
        if (this.nativeViewProtected && this._loadOnDemandModeInternal) {
            if (commonModule.ListViewLoadOnDemandMode.Auto === this._loadOnDemandModeInternal) {
                this.nativeViewProtected.loadOnDemandMode = 2 /* TKListViewLoadOnDemandMode.Auto */;
            }
            else if (commonModule.ListViewLoadOnDemandMode.Manual === this._loadOnDemandModeInternal) {
                this.nativeViewProtected.loadOnDemandMode = 1 /* TKListViewLoadOnDemandMode.Manual */;
            }
            else
                this.nativeViewProtected.loadOnDemandMode = 0 /* TKListViewLoadOnDemandMode.None */;
        }
    }
    onLoadOnDemandBufferSizeChanged(oldValue, newValue) {
        this.syncLoadOnDemandBufferSize();
    }
    syncLoadOnDemandBufferSize() {
        if (this.loadOnDemandBufferSize !== undefined && this.nativeViewProtected) {
            this.nativeViewProtected.loadOnDemandBufferSize = this.loadOnDemandBufferSize;
        }
    }
    onSelectionBehaviorChanged(oldValue, newValue) {
        this.syncSelectionBehavior();
    }
    syncSelectionBehavior() {
        if (this.selectionBehavior && this.nativeViewProtected) {
            if (commonModule.ListViewSelectionBehavior.Press === this.selectionBehavior) {
                this.nativeViewProtected.selectionBehavior = 1 /* TKListViewSelectionBehavior.Press */;
            }
            else if (commonModule.ListViewSelectionBehavior.LongPress === this.selectionBehavior) {
                this.nativeViewProtected.selectionBehavior = 2 /* TKListViewSelectionBehavior.LongPress */;
            }
            else
                this.nativeViewProtected.selectionBehavior = 0 /* TKListViewSelectionBehavior.None */;
        }
    }
    getDataItem(index) {
        return this.items.getItem ? this.items.getItem(index) : this.items[index];
    }
    _getDataItemFromSection(index, section, isGroup) {
        const dataSourceImp = this._dataSource;
        if (!dataSourceImp || dataSourceImp.nativeTKDataSource.items.count <= section || dataSourceImp.nativeTKDataSource.items[section].items.count <= index) {
            return this.getDataItem(index);
        }
        const dataItem = dataSourceImp.nativeTKDataSource.items[section].items[index];
        let value = null;
        if (isGroup) {
            value = { category: this.groupingFunction(dataItem) };
        }
        else {
            value = dataItem;
        }
        return value ? value : this.getDataItem(index);
    }
    prepareItem(item, index, section) {
        if (!item) {
            return;
        }
        item.bindingContext = this.getDataItem(index);
    }
    prepareItemFromSection(item, index, section) {
        if (!item) {
            return;
        }
        item.bindingContext = this._getDataItemFromSection(index, section);
    }
    [verticalAlignmentProperty.setNative](value) {
        this.updateAlignment();
    }
    updateAlignment() {
        const value = this.verticalAlignment;
        const view = this.nativeViewProtected;
        if (!view) {
            return;
        }
        const contentSize = view.layout.collectionViewContentSize;
        const factor = value === 'middle' ? 2 : 1;
        const contentTop = value === 'bottom' || value === 'middle' ? Math.max((view.bounds.size.height - contentSize.height) / factor, 0) : 0;
        if (view.contentInset.top !== contentTop) {
            view.contentInset = new UIEdgeInsets({
                bottom: 0,
                left: 0,
                top: contentTop,
                right: 0,
            });
        }
    }
    requestLayout() {
        // When preparing cell don't call super - no need to invalidate our measure when cell desiredSize is changed.
        if (!this._preparingCell) {
            super.requestLayout();
            clearTimeout(this.timeout);
            if (this.nativeView) {
                this.timeout = setTimeout(() => {
                    const view = this.nativeViewProtected;
                    if (!view) {
                        return;
                    }
                    const context = UICollectionViewLayoutInvalidationContext.new();
                    context.invalidateItemsAtIndexPaths(view.indexPathsForVisibleItems);
                    view.layout.invalidateLayoutWithContext(context);
                    // view.
                    // view.layout.collectionViewContentSize.height
                    // view.intrinsicContentSize.height
                }, 0);
            }
        }
    }
    onLayout(left, top, right, bottom) {
        super.onLayout(left, top, right, bottom);
        this.updateAlignment();
    }
    onMeasure(widthMeasureSpec, heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (this._currentHeightSpec !== heightMeasureSpec || this._currentWidthSpec !== widthMeasureSpec) {
            this._currentWidthSpec = widthMeasureSpec;
            this._currentHeightSpec = heightMeasureSpec;
            this.updateHeaderFooter();
        }
    }
    get _childrenCount() {
        const count = 0;
        if (this._realizedCells) {
            const currentSize = this._realizedCells.size;
            if (this.isSwipeEnabled() === true) {
                return currentSize * 2;
            }
            return currentSize;
        }
        return count;
    }
    eachChildView(callback) {
        if (this._realizedCells) {
            this._realizedCells.forEach(function (value, key) {
                if (value) {
                    // if data issue with RLV, upon destroy this can end up empty, guard it
                    if (value.view && value.view.itemView) {
                        callback(value.view.itemView);
                    }
                    if (value.view && value.view.itemSwipeView) {
                        callback(value.view.itemSwipeView);
                    }
                    if (value instanceof ExtendedHeaderCell) {
                        callback(value.view);
                    }
                    if (value instanceof ExtendedFooterCell) {
                        callback(value.view);
                    }
                }
            }, this);
        }
    }
    onLoaded() {
        super.onLoaded();
        this.nativeViewProtected.delegate = this._delegate;
        if (this._isDataDirty) {
            this.refresh();
        }
    }
    onUnloaded() {
        super.onUnloaded();
        if (this.nativeViewProtected) {
            this.nativeViewProtected.delegate = null;
        }
    }
    scrollWithAmount(amount, animate) {
        if (this.nativeViewProtected) {
            const layoutVertical = this.listViewLayout.scrollDirection === commonModule.ListViewScrollDirection.Vertical ? true : false;
            const currentOffset = this.nativeViewProtected.contentOffset;
            if (layoutVertical) {
                this.nativeViewProtected.setContentOffsetAnimated(new CGPoint({ x: currentOffset.x, y: amount + currentOffset.y }), animate);
            }
            else {
                this.nativeViewProtected.setContentOffsetAnimated(new CGPoint({ x: amount + currentOffset.x, y: currentOffset.y }), animate);
            }
        }
    }
    getScrollOffset() {
        if (!this.nativeViewProtected) {
            return super.getScrollOffset();
        }
        if (this.listViewLayout.scrollDirection === commonModule.ListViewScrollDirection.Vertical) {
            const verticalOffset = this.nativeViewProtected.safeAreaInsets ? this.nativeViewProtected.safeAreaInsets.top : 0;
            return this.nativeViewProtected.contentOffset.y + verticalOffset;
        }
        else {
            const horizontalOffset = this.nativeViewProtected.safeAreaInsets ? this.nativeViewProtected.safeAreaInsets.left : 0;
            return this.nativeViewProtected.contentOffset.x + horizontalOffset;
        }
    }
    resolveNativeSnapPosition(snapMode) {
        if (snapMode) {
            let nativeSnapMode = 0 /* UICollectionViewScrollPosition.None */;
            if (this.listViewLayout.scrollDirection === commonModule.ListViewScrollDirection.Vertical) {
                switch (snapMode) {
                    case commonModule.ListViewItemSnapMode.Start:
                        nativeSnapMode = 1 /* UICollectionViewScrollPosition.Top */;
                        break;
                    case commonModule.ListViewItemSnapMode.End:
                        nativeSnapMode = 4 /* UICollectionViewScrollPosition.Bottom */;
                        break;
                    case commonModule.ListViewItemSnapMode.Center:
                        nativeSnapMode = 2 /* UICollectionViewScrollPosition.CenteredVertically */;
                        break;
                }
            }
            else {
                switch (snapMode) {
                    case commonModule.ListViewItemSnapMode.Start:
                        nativeSnapMode = 8 /* UICollectionViewScrollPosition.Left */;
                        break;
                    case commonModule.ListViewItemSnapMode.End:
                        nativeSnapMode = 32 /* UICollectionViewScrollPosition.Right */;
                        break;
                    case commonModule.ListViewItemSnapMode.Center:
                        nativeSnapMode = 16 /* UICollectionViewScrollPosition.CenteredHorizontally */;
                        break;
                }
            }
            return nativeSnapMode;
        }
        if (!this.scrollPosition) {
            if (this.listViewLayout.scrollDirection === commonModule.ListViewScrollDirection.Vertical) {
                return 1 /* UICollectionViewScrollPosition.Top */;
            }
            else {
                return 8 /* UICollectionViewScrollPosition.Left */;
            }
        }
        else {
            switch (this.scrollPosition) {
                case commonModule.ListViewScrollPosition.Bottom:
                    return 4 /* UICollectionViewScrollPosition.Bottom */;
                case commonModule.ListViewScrollPosition.CenteredHorizontally:
                    return 16 /* UICollectionViewScrollPosition.CenteredHorizontally */;
                case commonModule.ListViewScrollPosition.CenteredVertically:
                    return 2 /* UICollectionViewScrollPosition.CenteredVertically */;
                case commonModule.ListViewScrollPosition.Left:
                    return 8 /* UICollectionViewScrollPosition.Left */;
                case commonModule.ListViewScrollPosition.None:
                    return 0 /* UICollectionViewScrollPosition.None */;
                case commonModule.ListViewScrollPosition.Right:
                    return 32 /* UICollectionViewScrollPosition.Right */;
                case commonModule.ListViewScrollPosition.Top:
                    return 1 /* UICollectionViewScrollPosition.Top */;
            }
        }
    }
    scrollToIndex(index, animate = false, snapMode = commonModule.ListViewItemSnapMode.Auto) {
        if (this.nativeViewProtected) {
            const snapPosition = this.resolveNativeSnapPosition(snapMode);
            let item = index;
            let section = 0;
            if (this.isDataOperationsEnabled) {
                const manipulatedIndexPath = this.getItemIndexPath(index);
                if (manipulatedIndexPath) {
                    item = manipulatedIndexPath.row;
                    section = manipulatedIndexPath.section;
                }
                else {
                    item = undefined;
                    section = undefined;
                }
            }
            if (item !== undefined && section !== undefined) {
                this.nativeViewProtected.scrollToItemAtIndexPathAtScrollPositionAnimated(NSIndexPath.indexPathForItemInSection(item, section), snapPosition, animate);
            }
            else {
                console.log('Warning: Cannot scroll to element with index: ' + index + ' because it is not in the manipulated items collection.');
            }
        }
    }
    getItemIndexPath(index) {
        if (this.isDataOperationsEnabled && this._dataSource && this._dataSource.nativeTKDataSource) {
            return this._dataSource.nativeTKDataSource.findItem(this.getItemAtIndex(index));
        }
        else {
            return NSIndexPath.indexPathForItemInSection(index, 0);
        }
    }
    _getIndexForIndexPath(indexPath) {
        let index;
        if (!this.isDataOperationsEnabled) {
            index = indexPath.row;
        }
        else {
            const tappedItem = this._getDataItemFromSection(indexPath.row, indexPath.section);
            index = this.getIndexOf(tappedItem);
        }
        return index;
    }
    notifyPullToRefreshFinished(enableLoadOnDemand) {
        if (enableLoadOnDemand) {
            this._shouldReEnableLoadOnDemand = true;
            if (!this._insertingItemsWithAnimation) {
                this._returnLoadOnDemandMode();
            }
        }
        if (this.nativeViewProtected) {
            this.nativeViewProtected.didRefreshOnPull();
        }
    }
    notifyLoadOnDemandFinished(disableLoadOnDemand) {
        this.notifyLoadOnDemandFinishedImpl(null, disableLoadOnDemand);
    }
    notifyAppendItemsOnDemandFinished(itemsCount, disableLoadOnDemand) {
        this.notifyLoadOnDemandFinishedImpl(itemsCount, disableLoadOnDemand);
    }
    notifyLoadOnDemandFinishedImpl(appendedItemsCount, disableLoadOnDemand) {
        if (disableLoadOnDemand) {
            this._shouldDisableLoadOnDemand = true;
            if (!this._insertingItemsWithAnimation) {
                this._disableLoadOnDemand();
            }
        }
        if (this.nativeViewProtected) {
            if (appendedItemsCount !== null && appendedItemsCount >= 0) {
                // Refresh only affected items. Optimized version for the case when
                // only new items have been appended to the list.
                this.nativeViewProtected.didAppendItemsOnDemand(appendedItemsCount);
            }
            else {
                // Generic reload (significantly slower)
                this.nativeViewProtected.didLoadDataOnDemand();
            }
        }
    }
    _disableLoadOnDemand() {
        this._shouldDisableLoadOnDemand = false;
        this.setLoadOnDemandModeInternal(commonModule.ListViewLoadOnDemandMode.None);
    }
    // TODO: This can be used for https://github.com/telerik/nativescript-ui-feedback/issues/790
    _returnLoadOnDemandMode() {
        this._shouldReEnableLoadOnDemand = false;
        if (this.loadOnDemandMode) {
            this.setLoadOnDemandModeInternal(this.loadOnDemandMode);
        }
    }
    notifySwipeToExecuteFinished() {
        if (this.nativeViewProtected) {
            this.nativeViewProtected.endSwipe(true);
        }
    }
    refresh() {
        super.refresh();
        this._realizedCells.forEach((cell, nativeView, map) => {
            if (!(cell.view.bindingContext instanceof Observable)) {
                cell.view.bindingContext = null;
            }
        });
        if (this.isLoaded) {
            this.reloadDataSource();
            this.nativeViewProtected.reloadData();
            this.requestLayout();
            const args = {
                eventName: commonModule.RadListView.dataPopulatedEvent,
                object: this,
            };
            this.notify(args);
            this._isDataDirty = false;
        }
        else {
            this._isDataDirty = true;
        }
    }
    onSourceCollectionChanged(data) {
        if (!this.nativeViewProtected) {
            return;
        }
        if (this.isDataOperationsEnabled) {
            const myArray = [];
            this.items.forEach((element) => {
                myArray.push(element);
            });
            this._dataSource.nativeTKDataSource.itemSource = myArray;
            this.nativeViewProtected.reloadData();
            return;
        }
        if (data.action === ChangeType.Delete) {
            const nativeSource = NSMutableArray.new();
            nativeSource.addObject(NSIndexPath.indexPathForRowInSection(data.index, 0));
            this.unbindUnusedCells(data.removed);
            this.nativeViewProtected.deleteItemsAtIndexPaths(nativeSource);
        }
        else if (data.action === ChangeType.Add) {
            const nativePaths = NSMutableArray.alloc().init();
            for (let i = 0; i < data.addedCount; i++) {
                nativePaths.addObject(NSIndexPath.indexPathForRowInSection(data.index + i, 0));
            }
            if (this.nativeViewProtected.collectionView.dragging) {
                // Adjust the content offset to force stop the drag:
                this.nativeViewProtected.collectionView.setContentOffsetAnimated(this.nativeViewProtected.collectionView.contentOffset, false);
            }
            this.nativeViewProtected.insertItemsAtIndexPaths(nativePaths);
            // Reload the items to avoid duplicate Load on Demand indicators:
            this.nativeViewProtected.collectionView.reloadItemsAtIndexPaths(nativePaths);
        }
        else if (data.action === ChangeType.Splice) {
            if (data.removed && data.removed.length > 0) {
                const nativeSource = NSMutableArray.new();
                for (let i = 0; i < data.removed.length; i++) {
                    nativeSource.addObject(NSIndexPath.indexPathForRowInSection(data.index + i, 0));
                }
                this.unbindUnusedCells(data.removed);
                this.nativeViewProtected.deleteItemsAtIndexPaths(nativeSource);
            }
            if (data.addedCount) {
                const nativeSource = NSMutableArray.new();
                for (let i = 0; i < data.addedCount; i++) {
                    nativeSource.addObject(NSIndexPath.indexPathForRowInSection(data.index + i, 0));
                }
                this.nativeViewProtected.insertItemsAtIndexPaths(nativeSource);
            }
        }
        else if (data.action === ChangeType.Update) {
            super.onSourceCollectionChanged(data);
        }
    }
    onItemViewDisposerChanged() { }
    onNativeScriptViewAddedChanged() { }
    // Clears all views and related views from all templates and also resets the realized cells.
    // Usage: Use when you want to fully clear all views created by the template parsing mechanisum of the RadListView.
    clearEmbeddedViews() {
        this.clearRealizedCells();
        if (this.itemViewDisposer !== undefined) {
            this.itemViewDisposer();
        }
    }
    unbindUnusedCells(removedDataItems) {
        this._realizedCells.forEach(function (value, key) {
            if (!value || !value.view || !value.view.itemView || !value.view.itemView.bindingContext) {
                return;
            }
            if (removedDataItems.indexOf(value.view.itemView.bindingContext) !== -1) {
                value.view.itemView.bindingContext = undefined;
                if (value.view.itemSwipeView) {
                    value.view.itemSwipeView.bindingContext = undefined;
                }
            }
        }, this);
    }
    getLoadOnDemandItemTemplateContent() {
        return this.getViewForViewType(commonModule.ListViewViewType.LoadOnDemandView);
    }
    _getItemTemplateType(indexPath) {
        const selector = this.itemTemplateSelector;
        let type = this._defaultTemplate.key;
        if (selector) {
            if (this.isDataOperationsEnabled) {
                const item = this._getDataItemFromSection(indexPath.item, indexPath.section, false);
                type = selector(item, this.items.indexOf(item), this.items);
            }
            else {
                type = selector(this.getItemAtIndex(indexPath.item), indexPath.item, this.items);
            }
        }
        return type.toLowerCase();
    }
    getItemTemplateContent(index, templateType) {
        const cellViews = new Object();
        const templatedView = this.getViewForViewType(commonModule.ListViewViewType.ItemView, templateType);
        templatedView['nsMainBackgroundColor'] = templatedView.backgroundColor;
        // Proxy containers should not get treated as layouts.
        // Wrap them in a real layout as well.
        if (templatedView instanceof ProxyViewContainer) {
            const parentView = new StackLayout();
            parentView.addChild(templatedView);
            cellViews.itemView = parentView;
        }
        else {
            cellViews.itemView = templatedView;
        }
        const templatedSwipeView = this.getViewForViewType(commonModule.ListViewViewType.ItemSwipeView);
        // Proxy containers should not get treated as layouts.
        // Wrap them in a real layout as well.
        if (templatedSwipeView instanceof ProxyViewContainer) {
            const parentView = new StackLayout();
            parentView.addChild(templatedSwipeView);
            cellViews.itemSwipeView = parentView;
        }
        else {
            cellViews.itemSwipeView = templatedSwipeView;
        }
        return cellViews;
    }
    layoutHeaderFooterCell(cell) {
        const scrollDirection = this.listViewLayout.scrollDirection;
        const sizeRestriction = {
            width: scrollDirection === commonModule.ListViewScrollDirection.Vertical ? this.getMeasuredWidth() : undefined,
            height: scrollDirection === commonModule.ListViewScrollDirection.Vertical ? undefined : this.getMeasuredHeight(),
        };
        const itemViewDimensions = this.measureCell(cell.view, sizeRestriction);
        const cellView = cell.view;
        if (cellView) {
            View.layoutChild(this, cellView, 0, 0, itemViewDimensions.measuredWidth, itemViewDimensions.measuredHeight);
        }
        return itemViewDimensions;
    }
    layoutLoadOnDemandCell(cell) {
        const scrollDirection = this.listViewLayout.scrollDirection;
        const sizeRestriction = {
            width: scrollDirection === commonModule.ListViewScrollDirection.Vertical ? this.getMeasuredWidth() : undefined,
            height: scrollDirection === commonModule.ListViewScrollDirection.Vertical ? undefined : this.getMeasuredHeight(),
        };
        const itemViewDimensions = this.measureCell(cell.view, sizeRestriction);
        const cellView = cell.view;
        if (cellView) {
            View.layoutChild(this, cellView, 0, 0, itemViewDimensions.measuredWidth, itemViewDimensions.measuredHeight);
        }
        return itemViewDimensions;
    }
    layoutCell(cell, indexPath) {
        const itemViewDimensions = this.measureCell(cell.view.itemView, indexPath);
        const cellView = cell.view.itemView;
        if (cellView && cellView['isLayoutRequired']) {
            View.layoutChild(this, cellView, 0, 0, itemViewDimensions.measuredWidth, itemViewDimensions.measuredHeight);
        }
        const swipeViewDimensions = this.measureCell(cell.view.itemSwipeView, { width: itemViewDimensions.measuredWidth, height: itemViewDimensions.measuredHeight });
        const backgroundView = cell.view.itemSwipeView;
        if (backgroundView && backgroundView['isLayoutRequired']) {
            View.layoutChild(this, backgroundView, 0, 0, swipeViewDimensions.measuredWidth, swipeViewDimensions.measuredHeight);
        }
        return itemViewDimensions;
    }
    measureCell(cellView, sizeRestriction) {
        if (cellView) {
            const listViewLayout = this.listViewLayout;
            let itemWidth = isNaN(listViewLayout.itemWidth) ? undefined : Utils.layout.toDevicePixels(listViewLayout.itemWidth);
            let itemHeight = isNaN(listViewLayout.itemHeight) ? undefined : Utils.layout.toDevicePixels(listViewLayout.itemHeight);
            if (sizeRestriction !== undefined) {
                itemWidth = sizeRestriction.width;
                itemHeight = sizeRestriction.height;
            }
            let heightSpec, widthSpec;
            const spanCount = !isNaN(listViewLayout.spanCount) ? listViewLayout.spanCount : 1;
            if (listViewLayout.scrollDirection === commonModule.ListViewScrollDirection.Vertical) {
                itemWidth = itemWidth === undefined ? this.getMeasuredWidth() / spanCount : itemWidth;
                if (itemHeight === undefined) {
                    heightSpec = Utils.layout.makeMeasureSpec(0, Utils.layout.UNSPECIFIED);
                }
                else {
                    heightSpec = Utils.layout.makeMeasureSpec(itemHeight, Utils.layout.EXACTLY);
                }
                widthSpec = Utils.layout.makeMeasureSpec(itemWidth, Utils.layout.EXACTLY);
            }
            else {
                itemHeight = itemHeight === undefined ? this.getMeasuredHeight() / spanCount : itemHeight;
                if (itemWidth === undefined) {
                    widthSpec = Utils.layout.makeMeasureSpec(0, Utils.layout.UNSPECIFIED);
                }
                else {
                    widthSpec = Utils.layout.makeMeasureSpec(itemWidth, Utils.layout.EXACTLY);
                }
                heightSpec = Utils.layout.makeMeasureSpec(itemHeight, Utils.layout.EXACTLY);
            }
            return View.measureChild(this, cellView, widthSpec, heightSpec);
        }
        return undefined;
    }
    prepareCellTag(cell) {
        cell.tag = this._nextCellTag + 1;
        this._nextCellTag++;
        this._realizedCells.set(cell.tag, cell);
    }
    prepareLoadOnDemandCell(cell, indexPath) {
        if (cell.view === undefined) {
            const loadOnDemandView = this.getLoadOnDemandItemTemplateContent();
            if (loadOnDemandView) {
                cell.view = loadOnDemandView;
                this.disableIosOverflowSafeArea(cell.view);
                this.prepareCellTag(cell);
                cell.view.bindingContext = this.bindingContext;
                this._addView(cell.view);
                cell.contentView.addSubview(cell.view.ios);
            }
        }
        this.layoutLoadOnDemandCell(cell);
    }
    prepareHeaderCell(headerCell, indexPath) {
        const viewType = this.groupingFunction ? commonModule.ListViewViewType.GroupView : commonModule.ListViewViewType.HeaderView;
        this.prepareHeaderFooterCell(headerCell, viewType, indexPath);
    }
    prepareFooterCell(footerCell, indexPath) {
        this.prepareHeaderFooterCell(footerCell, commonModule.ListViewViewType.FooterView, indexPath);
    }
    prepareHeaderFooterCell(cell, viewType, indexPath) {
        if (cell.view === undefined || cell.view.parent === undefined || this.isDataOperationsEnabled) {
            if (cell.view !== undefined) {
                cell.view.ios.removeFromSuperview();
                cell.view = undefined;
            }
            cell.view = this.getSupplementaryView(indexPath, this.getViewForViewType(viewType));
            this.disableIosOverflowSafeArea(cell.view);
            this.prepareCellTag(cell);
            if (cell.view) {
                this.updateHeaderFooterBindingContext(cell, indexPath);
                this._addView(cell.view);
                this.layoutHeaderFooterCell(cell);
                cell.contentView.addSubview(cell.view.ios);
            }
        }
        else {
            this.updateHeaderFooterBindingContext(cell, indexPath);
        }
    }
    getSupplementaryView(indexPath, originalTemplateView) {
        let suplementaryView;
        if (this.isDataOperationsEnabled && indexPath.section === 0) {
            const templateView = this.getViewForViewType(commonModule.ListViewViewType.HeaderView);
            if (templateView) {
                templateView.row = 0;
                originalTemplateView.row = 1;
                const parentView = new GridLayout();
                parentView.addRow(new ItemSpec(0, GridUnitType.AUTO));
                parentView.addRow(new ItemSpec(1, GridUnitType.AUTO));
                parentView.addChild(templateView);
                parentView.addChild(originalTemplateView);
                if (this.nativeScriptViewAdded) {
                    this.nativeScriptViewAdded(parentView, originalTemplateView);
                    parentView[commonModule.NG_VIEW] = originalTemplateView[commonModule.NG_VIEW];
                }
                suplementaryView = parentView;
            }
            else {
                suplementaryView = originalTemplateView;
            }
        }
        else {
            suplementaryView = originalTemplateView;
        }
        return suplementaryView;
    }
    updateHeaderFooterBindingContext(cell, indexPath) {
        const context = this.getBindingContext(indexPath);
        cell.view.bindingContext = context;
        const args = {
            eventName: commonModule.RadListView.itemLoadingInternalEvent,
            object: this,
            index: -1,
            view: cell.view,
            ios: cell,
        };
        this.notify(args);
        if (args.view !== cell.view) {
            // view has been changed on the event handler
            cell.view = args.view;
            this.disableIosOverflowSafeArea(cell.view);
            this.prepareCellTag(cell);
            if (cell.view) {
                cell.view.bindingContext = context;
            }
        }
    }
    getBindingContext(indexPath) {
        if (!this.isDataOperationsEnabled || !this.groupingFunction) {
            return this.bindingContext;
        }
        else {
            return this._getDataItemFromSection(0, indexPath.section, true);
        }
    }
    // This is needed by https://github.com/NativeScript/NativeScript/pull/6656
    disableIosOverflowSafeArea(parentView) {
        if (parentView) {
            parentView.iosOverflowSafeAreaEnabled = false;
        }
    }
    hideCell(cell, indexPath) {
        const internalLoadingArgs = {
            eventName: commonModule.RadListView.itemRecyclingInternalEvent,
            object: this,
            index: this._getIndexForIndexPath(indexPath),
            view: cell.view ? cell.view.itemView : null,
            ios: cell,
        };
        this.notify(internalLoadingArgs);
    }
    showCell(cell, indexPath) {
        const internalLoadingArgs = {
            eventName: commonModule.RadListView.itemReapperaingInternalEvent,
            object: this,
            index: this._getIndexForIndexPath(indexPath),
            view: cell.view ? cell.view.itemView : null,
            ios: cell,
        };
        this.notify(internalLoadingArgs);
    }
    prepareCell(tableCell, indexPath, templateType, raiseItemLoadingEvent) {
        const cell = tableCell;
        if (cell.view === undefined) {
            cell.view = this.getItemTemplateContent(indexPath.item, templateType);
            this.disableIosOverflowSafeArea(cell.view.itemView);
            this.disableIosOverflowSafeArea(cell.view.swipeView);
            this.prepareCellTag(cell);
            if (this.reorderMode && this.reorderMode === commonModule.ListViewReorderMode.Drag) {
                let reorderHandle = undefined;
                cell.view.itemView.eachChildView(function (view) {
                    if (view instanceof ReorderHandle) {
                        reorderHandle = view;
                        return false;
                    }
                    return true;
                });
                if (reorderHandle) {
                    // At this point the cell is not yet added to the layout,
                    // so its nativeView is not initialized. We call _setupUI to
                    // force the creation of the nativeView.
                    reorderHandle._setupUI({});
                    cell.reorderHandle = reorderHandle.ios;
                }
            }
        }
        if (cell.view.itemView && !cell.view.itemView.parent) {
            if (cell.myContentView && cell.myContentView.ios) {
                cell.myContentView.ios.removeFromSuperview();
                cell.myContentView = null;
            }
            this._addView(cell.view.itemView);
            cell.myContentView = cell.view.itemView;
            if (cell.contentView.subviews && cell.contentView.subviews.count > 0) {
                cell.contentView.insertSubviewBelowSubview(cell.view.itemView.ios, cell.contentView.subviews.objectAtIndex(0));
            }
            else {
                cell.contentView.addSubview(cell.view.itemView.ios);
            }
        }
        if (!this.isDataOperationsEnabled) {
            this.prepareItem(cell.view.itemView, indexPath.row);
        }
        else {
            this.prepareItemFromSection(cell.view.itemView, indexPath.row, indexPath.section);
        }
        this._toggleSelectionColor(cell.view.itemView, this.isItemSelected(cell.view.itemView.bindingContext));
        if (cell.view.itemSwipeView && !cell.view.itemSwipeView.parent) {
            if (cell.myBackgroundView && cell.myBackgroundView.ios) {
                cell.myBackgroundView.ios.removeFromSuperview();
                cell.myBackgroundView = null;
            }
            cell.myBackgroundView = cell.view.itemSwipeView;
            this._addView(cell.view.itemSwipeView);
            cell.swipeBackgroundView.addSubview(cell.view.itemSwipeView.ios);
        }
        if (!this.isDataOperationsEnabled) {
            this.prepareItem(cell.view.itemSwipeView, indexPath.row);
        }
        else {
            this.prepareItemFromSection(cell.view.itemSwipeView, indexPath.row, indexPath.section);
        }
        const internalLoadingArgs = {
            eventName: commonModule.RadListView.itemLoadingInternalEvent,
            object: this,
            index: this._getIndexForIndexPath(indexPath),
            view: cell.view ? cell.view.itemView : null,
            ios: cell,
        };
        this.notify(internalLoadingArgs);
        if (cell && cell.view && cell.view.itemView) {
            // notify event handler could change itemView and could end up null/undefined
            if (internalLoadingArgs.view && internalLoadingArgs.view !== cell.view.itemView) {
                // view has been changed on the event handler
                this._removeView(cell.view.itemView);
                cell.view.itemView = internalLoadingArgs.view;
                this.prepareCell(cell, indexPath, templateType, raiseItemLoadingEvent);
                return;
            }
        }
        if (raiseItemLoadingEvent) {
            const args = {
                eventName: commonModule.RadListView.itemLoadingEvent,
                object: this,
                index: this._getIndexForIndexPath(indexPath),
                view: cell.view ? cell.view.itemView : null,
                ios: cell,
            };
            this.notify(args);
            if (cell && cell.view && cell.view.itemView) {
                // notify event handler could change itemView and could end up null/undefined
                if (args.view && args.view !== cell.view.itemView) {
                    // view has been changed on the event handler
                    this._removeView(cell.view.itemView);
                    cell.view.itemView = args.view;
                    this.prepareCell(cell, indexPath, templateType, raiseItemLoadingEvent);
                }
            }
        }
    }
    getFirstVisiblePosition() {
        let firstIndex = undefined;
        if (this.nativeView) {
            const cells = this.nativeView.collectionView.visibleCells;
            const visibleIndexes = [];
            for (let i = 0; i < cells.count; i++) {
                const indexPath = this.nativeView.collectionView.indexPathForCell(cells[i]);
                visibleIndexes.push(indexPath.row);
            }
            firstIndex = visibleIndexes.sort(function (a, b) {
                return a - b;
            })[0];
        }
        return firstIndex;
    }
}
//# sourceMappingURL=index.ios.js.map