import { ListViewBase, separatorColorProperty, itemTemplatesProperty, stickyHeaderProperty, stickyHeaderTemplateProperty, sectionedProperty, showSearchProperty } from './list-view-common';
import { View } from '../core/view';
import { PercentLength } from '../styling/length-shared';
import { unsetValue } from '../core/properties/property-shared';
import { Color } from '../../color';
import { Observable } from '../../data/observable';
import { StackLayout } from '../layouts/stack-layout';
import { ProxyViewContainer } from '../proxy-view-container';
import { LayoutBase } from '../layouts/layout-base';
import { profile } from '../../profiling';
import { Trace } from '../../trace';
import { Builder } from '../builder';
import { Label } from '../label';
export * from './list-view-common';
const ITEMLOADING = ListViewBase.itemLoadingEvent;
const LOADMOREITEMS = ListViewBase.loadMoreItemsEvent;
const ITEMTAP = ListViewBase.itemTapEvent;
const SEARCHCHANGE = ListViewBase.searchChangeEvent;
const STICKY_HEADER_Z_INDEX = 1000;
const SEARCH_VIEW_Z_INDEX = 2000;
// View type constants for sectioned lists
const ITEM_VIEW_TYPE = 0;
let ItemClickListener;
function initializeItemClickListener() {
    if (ItemClickListener) {
        return;
    }
    var ItemClickListenerImpl = (function (_super) {
        __extends(ItemClickListenerImpl, _super);
        function ItemClickListenerImpl(owner) {
            var _this = _super.call(this) || this;
            _this.owner = owner;
            return global.__native(_this);
        }
        ItemClickListenerImpl.prototype.onItemClick = function (parent, convertView, index, id) {
            var owner = this.owner;
            var view = owner._realizedItems.get(convertView).view;
            owner.notify({
                eventName: ITEMTAP,
                object: owner,
                index: index,
                view: view,
            });
        };
        ItemClickListenerImpl = __decorate([
            Interfaces([android.widget.AdapterView.OnItemClickListener])
        ], ItemClickListenerImpl);
        return ItemClickListenerImpl;
    }(java.lang.Object));
    ItemClickListener = ItemClickListenerImpl;
}
export class ListView extends ListViewBase {
    constructor() {
        super(...arguments);
        this._androidViewId = -1;
        this._realizedItems = new Map();
        this._availableViews = new Map();
        this._realizedTemplates = new Map();
        this._stickyHeaderHeight = 0;
        this._hiddenHeaderPositions = new Set(); // Track which headers to hide
    }
    get hasSearchView() {
        return !!this._searchView;
    }
    _ensureAvailableViews(templateKey) {
        if (!this._availableViews.has(templateKey)) {
            this._availableViews.set(templateKey, new Set());
        }
    }
    _registerViewToTemplate(templateKey, nativeView, view) {
        this._realizedItems.set(nativeView, {
            view,
            templateKey,
        });
        if (!this._realizedTemplates.has(templateKey)) {
            this._realizedTemplates.set(templateKey, new Map());
        }
        this._realizedTemplates.get(templateKey).set(nativeView, view);
        this._ensureAvailableViews(templateKey);
        const availableViews = this._availableViews.get(templateKey);
        availableViews.add(nativeView);
    }
    _markViewUsed(nativeView) {
        const viewData = this._realizedItems.get(nativeView);
        if (!viewData) {
            throw new Error('View not registered');
        }
        this._ensureAvailableViews(viewData.templateKey);
        this._availableViews.get(viewData.templateKey).delete(nativeView);
    }
    _markViewUnused(nativeView) {
        const viewData = this._realizedItems.get(nativeView);
        if (!viewData) {
            throw new Error('View not registered');
        }
        this._ensureAvailableViews(viewData.templateKey);
        this._availableViews.get(viewData.templateKey).add(nativeView);
    }
    _getKeyFromView(nativeView) {
        return this._realizedItems.get(nativeView).templateKey;
    }
    _hasAvailableView(templateKey) {
        this._ensureAvailableViews(templateKey);
        return this._availableViews.get(templateKey).size > 0;
    }
    _getAvailableView(templateKey) {
        this._ensureAvailableViews(templateKey);
        if (!this._hasAvailableView(templateKey)) {
            return null;
        }
        const view = this._availableViews.get(templateKey).values().next().value;
        this._markViewUsed(view);
        return view;
    }
    createNativeView() {
        const listView = new android.widget.ListView(this._context);
        listView.setDescendantFocusability(android.view.ViewGroup.FOCUS_AFTER_DESCENDANTS);
        // Fixes issue with black random black items when scrolling
        listView.setCacheColorHint(android.graphics.Color.TRANSPARENT);
        return listView;
    }
    initNativeView() {
        super.initNativeView();
        this.updateEffectiveRowHeight();
        const nativeView = this.nativeViewProtected;
        initializeItemClickListener();
        ensureListViewAdapterClass();
        const adapter = new ListViewAdapterClass(this);
        nativeView.setAdapter(adapter);
        nativeView.adapter = adapter;
        const itemClickListener = new ItemClickListener(this);
        nativeView.setOnItemClickListener(itemClickListener);
        nativeView.itemClickListener = itemClickListener;
        if (this._androidViewId < 0) {
            this._androidViewId = android.view.View.generateViewId();
        }
        nativeView.setId(this._androidViewId);
        // Don't setup search here - wait for onLoaded when context is properly available
    }
    disposeNativeView() {
        const nativeView = this.nativeViewProtected;
        nativeView.setAdapter(null);
        if (nativeView.itemClickListener) {
            nativeView.itemClickListener.owner = null;
        }
        if (nativeView.adapter) {
            nativeView.adapter.owner = null;
        }
        // Cleanup search
        this._cleanupSearchView();
        // Cleanup sticky header
        this._cleanupStickyHeader();
        this.clearRealizedCells();
        super.disposeNativeView();
    }
    _cleanupStickyHeader() {
        // Remove scroll listener
        if (this._scrollListener) {
            this.nativeViewProtected.setOnScrollListener(null);
            this._scrollListener = null;
        }
        // Remove sticky header from parent
        if (this._stickyHeaderView && this._stickyHeaderView.parent) {
            this._stickyHeaderView.parent._removeView(this._stickyHeaderView);
        }
        this._stickyHeaderView = null;
        this._stickyHeaderHeight = 0;
        // Clear hidden headers
        this._hiddenHeaderPositions.clear();
    }
    onLoaded() {
        super.onLoaded();
        // Without this call itemClick won't be fired... :(
        this.requestLayout();
        // Setup sticky header if enabled
        if (this.stickyHeader && this.sectioned && this.stickyHeaderTemplate) {
            this._setupStickyHeader();
        }
        // Setup search if enabled and not already set up
        if (this.showSearch && !this._searchView && this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
            this._setupSearchView();
        }
    }
    refresh() {
        const nativeView = this.nativeViewProtected;
        if (!nativeView || !nativeView.getAdapter()) {
            return;
        }
        // clear bindingContext when it is not observable because otherwise bindings to items won't reevaluate
        this._realizedItems.forEach(({ view }, nativeView) => {
            if (!(view.bindingContext instanceof Observable)) {
                view.bindingContext = null;
            }
        });
        // Safely refresh the adapter - no HeaderViewListAdapter issues since we don't use headers
        const adapter = nativeView.getAdapter();
        if (adapter instanceof android.widget.BaseAdapter) {
            try {
                adapter.notifyDataSetChanged();
            }
            catch (error) {
                if (Trace.isEnabled()) {
                    Trace.error('Error refreshing adapter, recreating: ' + error);
                }
                nativeView.setAdapter(new ListViewAdapterClass(this));
            }
        }
    }
    scrollToIndex(index) {
        const nativeView = this.nativeViewProtected;
        if (nativeView) {
            nativeView.setSelection(index);
        }
    }
    scrollToIndexAnimated(index) {
        const nativeView = this.nativeViewProtected;
        if (nativeView) {
            nativeView.smoothScrollToPosition(index);
        }
    }
    get _childrenCount() {
        return this._realizedItems.size;
    }
    eachChildView(callback) {
        this._realizedItems.forEach(({ view }, nativeView) => {
            if (view.parent instanceof ListView) {
                callback(view);
            }
            else {
                // in some cases (like item is unloaded from another place (like angular) view.parent becomes undefined)
                if (view.parent) {
                    callback(view.parent);
                }
            }
        });
    }
    _dumpRealizedTemplates() {
        console.log(`Realized Templates:`);
        this._realizedTemplates.forEach((value, index) => {
            console.log(`\t${index}:`);
            value.forEach((value, index) => {
                console.log(`\t\t${index.hashCode()}: ${value}`);
            });
        });
        console.log(`Realized Items Size: ${this._realizedItems.size}`);
    }
    clearRealizedCells() {
        // clear the cache
        this._realizedItems.forEach(({ view }, nativeView) => {
            if (view.parent) {
                // This is to clear the StackLayout that is used to wrap non LayoutBase & ProxyViewContainer instances.
                if (!(view.parent instanceof ListView)) {
                    this._removeView(view.parent);
                }
                view.parent._removeView(view);
            }
        });
        this._realizedItems.clear();
        this._availableViews.clear();
        this._realizedTemplates.clear();
    }
    isItemAtIndexVisible(index) {
        const nativeView = this.nativeViewProtected;
        const start = nativeView.getFirstVisiblePosition();
        const end = nativeView.getLastVisiblePosition();
        return index >= start && index <= end;
    }
    // Sticky header methods
    _setupStickyHeader() {
        if (!this.stickyHeader || !this.sectioned || !this.stickyHeaderTemplate) {
            return;
        }
        // Create the sticky header view
        this._createStickyHeaderView();
        // Add it as an overlay to the parent
        this._addStickyHeaderToParent();
        // Add padding to ListView so content doesn't hide behind sticky header
        this._addListViewPadding();
        // Setup scroll listener to update header content
        this._setupScrollListener();
    }
    _createStickyHeaderView() {
        if (this._stickyHeaderView) {
            return; // Already created
        }
        // Create header view using the same template as section headers
        if (typeof this.stickyHeaderTemplate === 'string') {
            try {
                this._stickyHeaderView = Builder.parse(this.stickyHeaderTemplate, this);
            }
            catch (error) {
                // Fallback to simple label
                this._stickyHeaderView = new Label();
                this._stickyHeaderView.text = 'Header Error';
            }
        }
        if (!this._stickyHeaderView) {
            // Default header
            this._stickyHeaderView = new Label();
            this._stickyHeaderView.text = 'Section 0';
        }
        // Set initial binding context (section 0)
        this._updateStickyHeader(0);
    }
    _addStickyHeaderToParent() {
        if (!this._stickyHeaderView || !this.parent) {
            return;
        }
        // Remove from current parent if it has one (likely the ListView from Builder.parse)
        if (this._stickyHeaderView.parent) {
            this._stickyHeaderView.parent._removeView(this._stickyHeaderView);
        }
        // Set proper sizing - don't stretch to fill parent
        this._stickyHeaderView.width = { unit: '%', value: 100 };
        this._stickyHeaderView.height = 'auto'; // Let it size to content
        this._stickyHeaderView.verticalAlignment = 'top';
        this._stickyHeaderView.horizontalAlignment = 'stretch';
        // Add sticky header to the parent layout
        // If search view exists, position sticky header after it (index 1), otherwise at top (index 0)
        const parentLayout = this.parent;
        const hasSearchView = this.showSearch && this._searchView && this._searchView._wrapper;
        if (parentLayout instanceof StackLayout) {
            const insertIndex = hasSearchView ? 1 : 0;
            parentLayout.insertChild(this._stickyHeaderView, insertIndex);
        }
        else {
            parentLayout._addView(this._stickyHeaderView);
        }
        // When search is enabled, position sticky header below search view with proper top margin
        if (this.showSearch && this._searchView) {
            // Add top margin to push sticky header below search view
            this._stickyHeaderView.marginTop = 0; // Reset any previous margin
            // Position sticky header with proper offset using native positioning
            if (this._stickyHeaderView.nativeViewProtected) {
                this._stickyHeaderView.nativeViewProtected.setZ(STICKY_HEADER_Z_INDEX);
                // Use a timeout to ensure search view is measured first
                setTimeout(() => {
                    if (this._searchView && this._searchView._wrapper) {
                        const searchWrapper = this._searchView._wrapper;
                        if (searchWrapper.nativeViewProtected) {
                            const searchHeight = searchWrapper.nativeViewProtected.getMeasuredHeight() || 50;
                            // Position sticky header below search view using translation
                            if (this._stickyHeaderView.nativeViewProtected) {
                                this._stickyHeaderView.nativeViewProtected.setTranslationY(searchHeight);
                            }
                        }
                    }
                }, 100);
            }
        }
        else {
            // No search view - position at top
            if (this._stickyHeaderView.nativeViewProtected) {
                this._stickyHeaderView.nativeViewProtected.setZ(STICKY_HEADER_Z_INDEX);
                this._stickyHeaderView.nativeViewProtected.setTranslationY(0);
            }
        }
    }
    _addListViewPadding() {
        if (!this._stickyHeaderView) {
            return;
        }
        // Calculate total top padding: search view height + sticky header height
        let searchViewHeight = 0;
        if (this.showSearch && this._searchView && this._searchView._wrapper) {
            const searchWrapper = this._searchView._wrapper;
            if (searchWrapper.nativeViewProtected && searchWrapper.nativeViewProtected.getMeasuredHeight() > 0) {
                searchViewHeight = searchWrapper.nativeViewProtected.getMeasuredHeight();
            }
            else {
                searchViewHeight = 50; // Default search view height
            }
        }
        // Apply immediate padding with defaults to prevent content hiding
        const defaultHeaderHeight = 50; // Reasonable default height in dp
        const totalPadding = searchViewHeight + defaultHeaderHeight;
        this.nativeViewProtected.setPadding(0, totalPadding, 0, 0);
        this._stickyHeaderHeight = defaultHeaderHeight;
        // Request layout to ensure proper measurement
        this._stickyHeaderView.requestLayout();
        // Then measure and adjust padding if needed using a layout listener for determinism
        const stickyHeaderNativeView = this._stickyHeaderView && this._stickyHeaderView.nativeViewProtected;
        if (stickyHeaderNativeView) {
            const layoutListener = new android.view.View.OnLayoutChangeListener({
                onLayoutChange: (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) => {
                    if (v.getMeasuredHeight() > 0) {
                        const measuredHeaderHeight = v.getMeasuredHeight();
                        let finalSearchHeight = searchViewHeight;
                        // Re-measure search view if needed
                        if (this.showSearch && this._searchView && this._searchView._wrapper) {
                            const searchWrapper = this._searchView._wrapper;
                            if (searchWrapper.nativeViewProtected && searchWrapper.nativeViewProtected.getMeasuredHeight() > 0) {
                                finalSearchHeight = searchWrapper.nativeViewProtected.getMeasuredHeight();
                            }
                        }
                        // Calculate final padding: search height + sticky header height + small buffer
                        const totalPaddingHeight = finalSearchHeight + measuredHeaderHeight + 4;
                        this._stickyHeaderHeight = measuredHeaderHeight;
                        this.nativeViewProtected.setPadding(0, totalPaddingHeight, 0, 0);
                        this.scrollToIndex(0);
                        // Remove the listener after first valid layout
                        v.removeOnLayoutChangeListener(layoutListener);
                    }
                },
            });
            stickyHeaderNativeView.addOnLayoutChangeListener(layoutListener);
        }
    }
    _setupScrollListener() {
        if (this._scrollListener) {
            return; // Already setup
        }
        const owner = this;
        this._scrollListener = new android.widget.AbsListView.OnScrollListener({
            onScrollStateChanged(view, scrollState) {
                // Not needed for sticky headers
            },
            onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount) {
                if (owner.sectioned && owner._stickyHeaderView) {
                    const currentSection = owner._getCurrentSection(firstVisibleItem);
                    owner._updateStickyHeader(currentSection);
                    // Hide section headers when they would appear right below sticky header
                    owner._updateHiddenHeaders(firstVisibleItem);
                }
            },
        });
        this.nativeViewProtected.setOnScrollListener(this._scrollListener);
    }
    _getCurrentSection(firstVisibleItem) {
        if (!this.sectioned) {
            return 0;
        }
        // Convert the first visible list position to section number
        let currentPosition = 0;
        const sectionCount = this._getSectionCount();
        for (let section = 0; section < sectionCount; section++) {
            // Check if firstVisibleItem is in this section (header or items)
            const sectionItems = this._getItemsInSection(section) || [];
            const itemsInSection = sectionItems.length || 0;
            const sectionEndPosition = currentPosition + 1 + itemsInSection; // +1 for header
            if (firstVisibleItem < sectionEndPosition) {
                return section;
            }
            currentPosition = sectionEndPosition;
        }
        return Math.max(0, sectionCount - 1); // Fallback to last section
    }
    _updateStickyHeader(section) {
        if (!this._stickyHeaderView) {
            return;
        }
        // Update binding context to match the current section
        const sectionData = this._getSectionData(section);
        if (sectionData) {
            this._stickyHeaderView.bindingContext = sectionData;
        }
        else {
            this._stickyHeaderView.bindingContext = { title: `Section ${section}`, section: section };
        }
    }
    _updateHiddenHeaders(firstVisibleItem) {
        const previousHiddenHeaders = new Set(this._hiddenHeaderPositions);
        this._hiddenHeaderPositions.clear();
        // If we're at the very top (first item is position 0, which is the first section header),
        // hide that section header to avoid duplication with sticky header
        if (firstVisibleItem === 0) {
            this._hiddenHeaderPositions.add(0); // Hide the first section header position
        }
        // If hidden headers changed, refresh the adapter
        const hiddenHeadersChanged = previousHiddenHeaders.size !== this._hiddenHeaderPositions.size || [...previousHiddenHeaders].some((pos) => !this._hiddenHeaderPositions.has(pos));
        if (hiddenHeadersChanged) {
            // Refresh adapter to update visibility
            const adapter = this.nativeViewProtected.getAdapter();
            if (adapter instanceof android.widget.BaseAdapter) {
                adapter.notifyDataSetChanged();
            }
        }
    }
    [separatorColorProperty.getDefault]() {
        const nativeView = this.nativeViewProtected;
        return {
            dividerHeight: nativeView.getDividerHeight(),
            divider: nativeView.getDivider(),
        };
    }
    [separatorColorProperty.setNative](value) {
        const nativeView = this.nativeViewProtected;
        if (value instanceof Color) {
            nativeView.setDivider(new android.graphics.drawable.ColorDrawable(value.android));
            nativeView.setDividerHeight(1);
        }
        else {
            nativeView.setDivider(value.divider);
            nativeView.setDividerHeight(value.dividerHeight);
        }
    }
    [itemTemplatesProperty.getDefault]() {
        return null;
    }
    [itemTemplatesProperty.setNative](value) {
        this._itemTemplatesInternal = new Array(this._defaultTemplate);
        if (value) {
            this._itemTemplatesInternal = this._itemTemplatesInternal.concat(value);
        }
        if (this.nativeViewProtected) {
            this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
            this.refresh();
        }
    }
    // Sticky header property handlers
    [stickyHeaderProperty.setNative](value) {
        // Refresh adapter to handle sectioned vs non-sectioned display
        if (this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
            this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
        }
        // Setup or cleanup sticky header
        if (value && this.sectioned && this.stickyHeaderTemplate && this.isLoaded) {
            this._setupStickyHeader();
        }
        else {
            this._cleanupStickyHeader();
        }
    }
    [stickyHeaderTemplateProperty.setNative](value) {
        // Refresh adapter when template changes
        if (this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
            this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
        }
        // Recreate sticky header with new template
        this._cleanupStickyHeader();
        if (value && this.stickyHeader && this.sectioned && this.isLoaded) {
            this._setupStickyHeader();
        }
    }
    [sectionedProperty.setNative](value) {
        // Refresh adapter to handle sectioned vs non-sectioned data
        if (this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
            this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
        }
        // Setup or cleanup sticky header based on sectioned state
        if (value && this.stickyHeader && this.stickyHeaderTemplate && this.isLoaded) {
            this._setupStickyHeader();
        }
        else {
            this._cleanupStickyHeader();
        }
    }
    // Search methods
    _setupSearchView() {
        if (this._searchView || !this.showSearch || !this.nativeViewProtected) {
            return;
        }
        // Create SearchView using the ListView's context
        this._searchView = new android.widget.SearchView(this.nativeViewProtected.getContext());
        this._searchView.setQueryHint('Search...');
        this._searchView.setIconifiedByDefault(false);
        this._searchView.setSubmitButtonEnabled(false);
        // Setup search listener
        const owner = this;
        this._searchListener = new android.widget.SearchView.OnQueryTextListener({
            onQueryTextChange(newText) {
                const args = {
                    eventName: SEARCHCHANGE,
                    object: owner,
                    text: newText,
                    android: owner._searchView,
                };
                owner.notify(args);
                return true;
            },
            onQueryTextSubmit(query) {
                const args = {
                    eventName: SEARCHCHANGE,
                    object: owner,
                    text: query,
                    android: owner._searchView,
                };
                owner.notify(args);
                return true;
            },
        });
        this._searchView.setOnQueryTextListener(this._searchListener);
        // Add search view to the parent container above the ListView
        this._addSearchToParent();
        // Add padding to ListView if no sticky header (otherwise sticky header method handles it)
        if (!this.stickyHeader || !this._stickyHeaderView) {
            this._addSearchPadding();
        }
    }
    _addSearchPadding() {
        if (!this._searchView) {
            return;
        }
        // Add basic padding for search view
        const defaultSearchHeight = 50; // Default search view height
        this.nativeViewProtected.setPadding(0, defaultSearchHeight, 0, 0);
        // Measure and adjust if needed
        setTimeout(() => {
            if (this._searchView && this._searchView._wrapper) {
                const searchWrapper = this._searchView._wrapper;
                if (searchWrapper.nativeViewProtected && searchWrapper.nativeViewProtected.getMeasuredHeight() > 0) {
                    const measuredHeight = searchWrapper.nativeViewProtected.getMeasuredHeight();
                    this.nativeViewProtected.setPadding(0, measuredHeight + 4, 0, 0);
                }
            }
        }, 100);
    }
    _addSearchToParent() {
        if (!this._searchView || !this.parent) {
            return;
        }
        // Get the parent layout
        const parentLayout = this.parent;
        // Create a simple NativeScript wrapper for the native SearchView
        const searchView = this._searchView;
        const searchViewWrapper = new (class extends View {
            createNativeView() {
                return searchView;
            }
        })();
        // Set layout properties - ensure it's at the top
        searchViewWrapper.height = 'auto';
        searchViewWrapper.width = { unit: '%', value: 100 };
        searchViewWrapper.verticalAlignment = 'top';
        searchViewWrapper.horizontalAlignment = 'stretch';
        // Always insert at position 0 (top) regardless of ListView position
        if (parentLayout instanceof StackLayout) {
            parentLayout.insertChild(searchViewWrapper, 0);
        }
        else {
            // For other layout types, add as first child
            parentLayout._addView(searchViewWrapper);
        }
        // Ensure search view appears above everything else
        if (searchViewWrapper.nativeViewProtected) {
            searchViewWrapper.nativeViewProtected.setZ(SEARCH_VIEW_Z_INDEX);
        }
        // Store reference for cleanup
        this._searchView._wrapper = searchViewWrapper;
    }
    _cleanupSearchView() {
        if (this._searchView) {
            // Remove search view wrapper from parent
            const wrapper = this._searchView._wrapper;
            if (wrapper && wrapper.parent) {
                wrapper.parent._removeView(wrapper);
            }
            // Clear listener
            if (this._searchListener) {
                this._searchView.setOnQueryTextListener(null);
                this._searchListener = null;
            }
            this._searchView = null;
            // Reset ListView padding if no sticky header
            if (!this.stickyHeader || !this._stickyHeaderView) {
                this.nativeViewProtected.setPadding(0, 0, 0, 0);
            }
        }
    }
    [showSearchProperty.setNative](value) {
        if (value) {
            if (this.isLoaded && this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
                this._setupSearchView();
                // Reposition sticky header if it exists
                if (this._stickyHeaderView) {
                    this._repositionStickyHeader();
                }
            }
        }
        else {
            this._cleanupSearchView();
            // Reposition sticky header if it exists
            if (this._stickyHeaderView) {
                this._repositionStickyHeader();
            }
        }
    }
    _repositionStickyHeader() {
        if (!this._stickyHeaderView || !this._stickyHeaderView.nativeViewProtected) {
            return;
        }
        // Reset positioning
        this._stickyHeaderView.nativeViewProtected.setTranslationY(0);
        // If search is enabled, position below search view
        if (this.showSearch && this._searchView && this._searchView._wrapper) {
            setTimeout(() => {
                const searchWrapper = this._searchView._wrapper;
                if (searchWrapper.nativeViewProtected) {
                    const searchHeight = searchWrapper.nativeViewProtected.getMeasuredHeight() || 50;
                    this._stickyHeaderView.nativeViewProtected.setTranslationY(searchHeight);
                }
            }, 100);
        }
        // Update ListView padding
        if (this.stickyHeader && this._stickyHeaderView) {
            this._addListViewPadding();
        }
    }
}
__decorate([
    profile,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", void 0)
], ListView.prototype, "createNativeView", null);
let ListViewAdapterClass;
function ensureListViewAdapterClass() {
    if (ListViewAdapterClass) {
        return;
    }
    var ListViewAdapter = (function (_super) {
        __extends(ListViewAdapter, _super);
        function ListViewAdapter(owner) {
            var _this = _super.call(this) || this;
            _this.owner = owner;
            return global.__native(_this);
        }
        ListViewAdapter.prototype.getCount = function () {
            if (!this.owner) {
                return 0;
            }
            var count = 0;
            if (this.owner.sectioned) {
                var sectionCount = this.owner._getSectionCount();
                if (!this.owner.items || sectionCount <= 0) {
                    return 0;
                }
                for (var i = 0; i < sectionCount; i++) {
                    var itemsInSection = this.owner._getItemsInSection(i) || [];
                    if (itemsInSection.length > 0) {
                        count += 1;
                        count += itemsInSection.length;
                    }
                }
            }
            else {
                var src = this.owner.items;
                count = src && typeof src.length === "number" ? src.length : 0;
            }
            return Math.max(0, count);
        };
        ListViewAdapter.prototype.getItem = function (i) {
            if (!this.owner || !this.owner.items) {
                return null;
            }
            var totalCount = this.getCount();
            if (i < 0 || i >= totalCount) {
                return null;
            }
            if (this.owner.sectioned) {
                var positionInfo = this._getPositionInfo(i);
                if (positionInfo.isHeader) {
                    return this.owner._getSectionData(positionInfo.section);
                }
                else {
                    return this.owner._getDataItemInSection(positionInfo.section, positionInfo.itemIndex);
                }
            }
            else {
                var src = this.owner.items;
                if (src && typeof src.length === "number" && i < src.length) {
                    var getItem = src.getItem;
                    return getItem ? getItem.call(src, i) : src[i];
                }
            }
            return null;
        };
        ListViewAdapter.prototype._getPositionInfo = function (position) {
            if (!this.owner.sectioned) {
                return { isHeader: false, section: 0, itemIndex: position };
            }
            var currentPosition = 0;
            var sectionCount = this.owner._getSectionCount();
            for (var section = 0; section < sectionCount; section++) {
                var itemsInSection = this.owner._getItemsInSection(section) || [];
                if (itemsInSection.length === 0) {
                    continue;
                }
                if (currentPosition === position) {
                    return { isHeader: true, section: section, itemIndex: -1 };
                }
                currentPosition++;
                if (position < currentPosition + itemsInSection.length) {
                    var itemIndex = position - currentPosition;
                    return { isHeader: false, section: section, itemIndex: itemIndex };
                }
                currentPosition += itemsInSection.length;
            }
            return { isHeader: false, section: 0, itemIndex: 0 };
        };
        ListViewAdapter.prototype.getItemId = function (i) {
            var item = this.getItem(i);
            var id = i;
            if (this.owner && item && this.owner.items) {
                id = this.owner.itemIdGenerator(item, i, this.owner.items);
            }
            return long(id);
        };
        ListViewAdapter.prototype.hasStableIds = function () {
            return true;
        };
        ListViewAdapter.prototype.isEnabled = function (position) {
            var totalCount = this.getCount();
            if (totalCount === 0 || position < 0 || position >= totalCount) {
                return false;
            }
            if (this.owner.sectioned) {
                var positionInfo = this._getPositionInfo(position);
                return !positionInfo.isHeader;
            }
            return true;
        };
        ListViewAdapter.prototype.getViewTypeCount = function () {
            var count = this.owner._itemTemplatesInternal.length;
            if (this.owner.sectioned && this.owner.stickyHeaderTemplate) {
                count += 1;
            }
            return count;
        };
        ListViewAdapter.prototype.getItemViewType = function (index) {
            if (this.owner.sectioned) {
                var positionInfo = this._getPositionInfo(index);
                if (positionInfo.isHeader) {
                    return this.owner._itemTemplatesInternal.length;
                }
                else {
                    var template = this.owner._getItemTemplate(positionInfo.itemIndex);
                    return this.owner._itemTemplatesInternal.indexOf(template);
                }
            }
            else {
                var template = this.owner._getItemTemplate(index);
                return this.owner._itemTemplatesInternal.indexOf(template);
            }
        };
        ListViewAdapter.prototype.getView = function (index, convertView, parent) {
            if (!this.owner) {
                return null;
            }
            var totalCount = this.getCount();
            if (index < 0 || index >= totalCount) {
                var emptyView = new android.view.View(this.owner._context);
                var layoutParams = new android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, 0);
                emptyView.setLayoutParams(layoutParams);
                return emptyView;
            }
            if (index === totalCount - 1) {
                this.owner.notify({
                    eventName: LOADMOREITEMS,
                    object: this.owner,
                });
            }
            if (this.owner.sectioned) {
                var positionInfo = this._getPositionInfo(index);
                if (positionInfo.isHeader) {
                    return this._createHeaderView(positionInfo.section, convertView, parent, index);
                }
                else {
                    return this._createItemView(positionInfo.section, positionInfo.itemIndex, convertView, parent);
                }
            }
            else {
                return this._createItemView(0, index, convertView, parent);
            }
        };
        ListViewAdapter.prototype._createHeaderView = function (section, convertView, parent, index) {
            if (this.owner._hiddenHeaderPositions.has(index)) {
                var emptyView = new android.view.View(this.owner._context);
                var layoutParams = new android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, 0);
                emptyView.setLayoutParams(layoutParams);
                return emptyView;
            }
            var headerView = null;
            var headerViewType = this.owner._itemTemplatesInternal.length;
            if (convertView) {
                var existingData = this.owner._realizedItems.get(convertView);
                if (existingData && existingData.templateKey === "header_".concat(headerViewType)) {
                    headerView = existingData.view;
                }
            }
            if (!headerView) {
                if (this.owner.stickyHeaderTemplate) {
                    if (typeof this.owner.stickyHeaderTemplate === "string") {
                        try {
                            headerView = Builder.parse(this.owner.stickyHeaderTemplate, this.owner);
                        }
                        catch (error) {
                            headerView = new Label();
                            headerView.text = "Header Error";
                        }
                    }
                }
                if (!headerView) {
                    headerView = new Label();
                    headerView.text = "Section ".concat(section);
                }
                if (!headerView.parent) {
                    if (headerView instanceof LayoutBase && !(headerView instanceof ProxyViewContainer)) {
                        this.owner._addView(headerView);
                        convertView = headerView.nativeViewProtected;
                    }
                    else {
                        var sp = new StackLayout();
                        sp.addChild(headerView);
                        this.owner._addView(sp);
                        convertView = sp.nativeViewProtected;
                    }
                }
                this.owner._realizedItems.set(convertView, {
                    view: headerView,
                    templateKey: "header_".concat(headerViewType),
                });
            }
            var sectionData = this.owner._getSectionData(section);
            if (sectionData) {
                headerView.bindingContext = sectionData;
            }
            else {
                headerView.bindingContext = { title: "Section ".concat(section), section: section };
            }
            return convertView;
        };
        ListViewAdapter.prototype._createItemView = function (section, itemIndex, convertView, parent) {
            var template = this.owner._getItemTemplate(itemIndex);
            var view;
            if (convertView && this.owner._getKeyFromView(convertView) !== template.key) {
                this.owner._markViewUnused(convertView);
                convertView = this.owner._getAvailableView(template.key);
            }
            if (convertView) {
                view = this.owner._realizedItems.get(convertView).view;
            }
            if (!view) {
                view = template.createView();
            }
            var args = {
                eventName: ITEMLOADING,
                object: this.owner,
                index: itemIndex,
                view: view,
                android: parent,
                ios: undefined,
            };
            if (this.owner.sectioned) {
                args.section = section;
            }
            this.owner.notify(args);
            if (!args.view) {
                args.view = this.owner._getDefaultItemContent(itemIndex);
            }
            if (args.view) {
                if (this.owner._effectiveRowHeight > -1) {
                    args.view.height = this.owner.rowHeight;
                }
                else {
                    args.view.height = unsetValue;
                }
                if (this.owner.sectioned) {
                    args.view._listViewItemIndex = itemIndex;
                    args.view._listViewSectionIndex = section;
                }
                if (this.owner.sectioned) {
                    this.owner._prepareItemInSection(args.view, section, itemIndex);
                }
                else {
                    this.owner._prepareItem(args.view, itemIndex);
                }
                if (!args.view.parent) {
                    if (args.view instanceof LayoutBase && !(args.view instanceof ProxyViewContainer)) {
                        var mt = PercentLength.toDevicePixels(args.view.marginTop, 0, Number.NaN);
                        var mb = PercentLength.toDevicePixels(args.view.marginBottom, 0, Number.NaN);
                        var ml = PercentLength.toDevicePixels(args.view.marginLeft, 0, Number.NaN);
                        var mr = PercentLength.toDevicePixels(args.view.marginRight, 0, Number.NaN);
                        var hasMargins = mt > 0 || mb > 0 || ml > 0 || mr > 0;
                        if (hasMargins) {
                            var outer = new StackLayout();
                            outer.addChild(args.view);
                            this.owner._addView(outer);
                            convertView = outer.nativeViewProtected;
                        }
                        else {
                            this.owner._addView(args.view);
                            convertView = args.view.nativeViewProtected;
                        }
                    }
                    else {
                        var sp = new StackLayout();
                        sp.addChild(args.view);
                        this.owner._addView(sp);
                        convertView = sp.nativeViewProtected;
                    }
                }
                this.owner._registerViewToTemplate(template.key, convertView, args.view);
                this.owner._markViewUsed(convertView);
            }
            return convertView;
        };
        __decorate([
            profile
        ], ListViewAdapter.prototype, "getView", null);
        return ListViewAdapter;
    }(android.widget.BaseAdapter));
    ListViewAdapterClass = ListViewAdapter;
}
//# sourceMappingURL=index.android.js.map