using System;
using System.Collections;
using System.Collections.Specialized;
using InABox.Core;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace InABox.Mobile
{

    
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MobileListView
    {
        
        public static readonly BindableProperty PullToRefreshProperty = BindableProperty.Create(
            nameof(PullToRefresh), 
            typeof(bool), 
            typeof(MobileListView),
            false);

        public bool PullToRefresh
        {
            get => (bool)GetValue(PullToRefreshProperty);
            set
            {
                SetValue(PullToRefreshProperty,value);
                _list.IsPullToRefreshEnabled = value;
                UpdateSummaryRow();
            }
        }

        private DataTemplate _itemTemplate;
        public DataTemplate ItemTemplate
        {
            get => _itemTemplate;
            set
            {
                _itemTemplate = value;
                _list.ItemTemplate = value;
            }
        }
        
        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
            nameof(ItemsSource), 
            typeof(IEnumerable), 
            typeof(MobileListView),
            propertyChanged:ItemsSourcePropertyChanged);

        private static void ItemsSourcePropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
        {
            (bindable as MobileListView)?.Refresh(newvalue as IEnumerable);
        }

        public IEnumerable ItemsSource
        {
            get => GetValue(ItemsSourceProperty) as IEnumerable;
            set => SetValue(ItemsSourceProperty, value);
        }

        private void Refresh(IEnumerable value)
        {
            if (_list.ItemsSource is INotifyCollectionChanged old)
                old.CollectionChanged -= ItemsSourceChanged;
            _list.ItemsSource = value;
            CheckChanged();
            if (value is INotifyCollectionChanged observable)
                observable.CollectionChanged += ItemsSourceChanged;
            UpdateSummaryRow(); 
        }

        public static readonly BindableProperty LastUpdatedProperty = BindableProperty.Create(
            nameof(LastUpdated), 
            typeof(DateTime), 
            typeof(MobileListView));
        
        public DateTime LastUpdated
        {
            get => (DateTime)GetValue(LastUpdatedProperty);
            set
            {
                SetValue(LastUpdatedProperty,value);
                UpdateSummaryRow();
            }
        }
        
        public static readonly BindableProperty ShowRecordCountProperty = BindableProperty.Create(
            nameof(ShowRecordCount), 
            typeof(bool), 
            typeof(MobileListView), 
            false);

        public bool ShowRecordCount
        {
            get => (bool)GetValue(ShowRecordCountProperty);
            set
            {
                SetValue(ShowRecordCountProperty,value);
                UpdateSummaryRow();
            }
        }
        
        public static readonly BindableProperty EmptyTextProperty = BindableProperty.Create(
            nameof(EmptyText), 
            typeof(string), 
            typeof(MobileListView), 
            "No Data Available");

        public string EmptyText
        {
            get => (string)GetValue(EmptyTextProperty);
            set => SetValue(EmptyTextProperty,value);
        }
        
        private void UpdateSummaryRow()
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                _lastupdate.IsVisible = !LastUpdated.IsEmpty();
                _lastupdate.Text = $"{DateTimeToAgeConverter.FormatTime(LastUpdated)}";
                _pulltorefresh.IsVisible = PullToRefresh;
                int count = (ItemsSource as IList)?.Count ?? 0;
                _numrecords.Text = $"{count} record{(count == 1 ? "" : "s")}";
                _numrecords.IsVisible = ShowRecordCount && ItemsSource is IList;
                _refreshcard.IsVisible = /*_lastupdate.IsVisible || */ _pulltorefresh.IsVisible || _numrecords.IsVisible;
                //_emptylist.IsVisible = !ShowRecordCount;
            });
        }

        private void ItemsSourceChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            CheckChanged();
            UpdateSummaryRow();
        }

        private void CheckChanged()
        {
            //_list.IsVisible = ItemsSource?.GetEnumerator().MoveNext() == true;
            //_nodata.IsVisible = !_list.IsVisible;
        }
        
        private bool _unevenrows;
        public bool HasUnevenRows
        {
            get => _unevenrows;
            set
            {
                _unevenrows = value;
                if (_list != null)
                    _list.HasUnevenRows = value;

            }
        }
        
        public event MobileListRefreshEvent RefreshRequested;

        public MobileListView()
        {
            InitializeComponent();
            _list.RefreshCommand = new Command(DoRefresh);
            HasUnevenRows = true;
        }
        
        private void DoRefresh(object sender)
        {
            if (PullToRefresh)
            {
                _list.IsRefreshing = true;
                RefreshRequested?.Invoke(sender, new MobileListRefreshEventArgs());
                _list.IsRefreshing = false;
            }
        }
        
    }
}