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

namespace InABox.Mobile
{

    public class MobileListRefreshEventArgs : EventArgs
    {
    }
    
    public delegate void MobileListRefreshEvent(object sender, MobileListRefreshEventArgs args);
    
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MobileCollectionView
    {
        
        public static readonly BindableProperty PullToRefreshProperty = BindableProperty.Create(
            nameof(PullToRefresh), 
            typeof(bool), 
            typeof(MobileCollectionView),
            false);

        public bool PullToRefresh
        {
            get => (bool)GetValue(PullToRefreshProperty);
            set
            {
                SetValue(PullToRefreshProperty,value);
                _refresher.IsEnabled = value;
                UpdateSummaryRow();
            }
        }
        
        public DataTemplate ItemTemplate
        {
            get => _list.ItemTemplate;
            set => _list.ItemTemplate = value;
        }
        
        public IEnumerable ItemsSource
        {
            get => _list.ItemsSource;
            set
            {
                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(MobileCollectionView));
        
        public DateTime LastUpdated
        {
            get => (DateTime)GetValue(LastUpdatedProperty);
            set
            {
                SetValue(LastUpdatedProperty,value);
                UpdateSummaryRow();
            }
        }
        
        public static readonly BindableProperty ShowRecordCountProperty = BindableProperty.Create(
            nameof(ShowRecordCount), 
            typeof(bool), 
            typeof(MobileCollectionView), 
            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(MobileCollectionView), 
            "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 double _spacing;
        public double Spacing
        {
            get => _spacing;
            set
            {
                _spacing = value;
                var layout = _list?.ItemsLayout as LinearItemsLayout;
                if (layout != null)
                    layout.ItemSpacing = _spacing;
            }
        }


        private bool _unevenrows;
        public bool HasUnevenRows
        {
            get => _unevenrows;
            set
            {
                _unevenrows = value;
                if (_list != null)
                    _list.ItemSizingStrategy =
                        value 
                            ? ItemSizingStrategy.MeasureAllItems 
                            : ItemSizingStrategy.MeasureFirstItem;
            }
        }
        
        public event MobileListRefreshEvent RefreshRequested;

        public MobileCollectionView()
        {
            InitializeComponent();
            _refresher.Command = new Command(DoRefresh);
            Spacing = 5;
            HasUnevenRows = true;
        }
        
        private void DoRefresh(object sender)
        {
            if (_refresher != null)
            {
                //var src = _list.ItemsSource;
                _list.ItemsSource = null;
                _refresher.IsRefreshing = true;
                RefreshRequested?.Invoke(sender, new MobileListRefreshEventArgs());
                _refresher.IsRefreshing = false;
                //_list.ItemsSource = src;
            }
        }
        
    }
}