using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using InABox.Core;
using Syncfusion.Data.Extensions;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using XF.Material.Forms;

namespace InABox.Mobile
{
    public class ToolGridLayoutChangedEventArgs : EventArgs
    {
        public int RowCount { get; private set; }
        public int ColCount { get; private set; }

        public ToolGridLayoutChangedEventArgs(int rowcount, int colcount)
        {
            RowCount = rowcount;
            ColCount = colcount;
        }
    }
    public delegate void ToolGridLayoutChangedEvent(object sender, ToolGridLayoutChangedEventArgs args);
    
    public class ToolGridViewModel : BindableObject
    {
        public CoreObservableCollection<IMobileToolItem> Items { get; private set; }

        public CoreObservableCollection<IMobileToolItem> VisibleItems { get; private set; }
        
        public int Columns { get; set; }

        private bool _disableUpdate = false;
        
        public void BeginUpdate() 
            => _disableUpdate = true;

        public void EndUpdate()
        {
            _disableUpdate = false;
            Refresh();
        }
        public ToolGridViewModel()
        {
            Columns = Device.Idiom == TargetIdiom.Tablet ? 6 : 4;
            VisibleItems = new CoreObservableCollection<IMobileToolItem>();

            Items = new CoreObservableCollection<IMobileToolItem>();
            Items.CollectionChanged += (sender, args) =>
            {

                if (args.OldItems != null)
                {
                    foreach (var item in args.OldItems?.OfType<MobileToolItem>())
                        item.VisibleChanged -= ItemChanged;
                }

                if (args.NewItems != null)
                {
                    foreach (var item in args.NewItems.OfType<MobileToolItem>())
                        item.VisibleChanged += ItemChanged;
                }

                Refresh();
            };
        }

        private void ItemChanged(object sender, EventArgs e) 
            => Refresh();

        public void Refresh()
        {
            if (_disableUpdate)
                return;
            
            VisibleItems.Clear();
            VisibleItems.AddRange(Items.Where(x => x.IsVisible).ToArray());
            int iRow = 0;
            int iCol = 0;
            bool bDirty = false;
            foreach (var item in VisibleItems)
            {
                bDirty = iRow != item.Row || iCol != item.Column;
                item.Row = iRow;
                item.Column = iCol;
                iCol++;
                if (iCol == Columns)
                {
                    iRow++;
                    iCol = 0;
                }
            }
            if (bDirty)
                LayoutChanged?.Invoke(this,new ToolGridLayoutChangedEventArgs(iRow,Columns));
        }

        public Color BackgroundColor { get; set; }

        public event ToolGridLayoutChangedEvent LayoutChanged;

    }
    
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MobileToolGrid
    {

        public IList<IMobileToolItem> Items => _viewModel.Items;
        
        public event EventHandler BeforeTap;
        public event EventHandler AfterTap;

        private ToolGridViewModel _viewModel = new();
        
        public void BeginUpdate()
        {
            _viewModel?.BeginUpdate();
        }

        public void EndUpdate()
        {
            _viewModel.EndUpdate();
        }
        
        public MobileToolGrid()
        {
            _viewModel.LayoutChanged += _viewModel_OnLayoutChanged;
            BeginUpdate();
            InitializeComponent();
            EndUpdate();
        }

        public void Refresh()
        {
            _viewModel.Refresh();
        }

        private readonly BindableProperty BorderColorProperty = BindableProperty.Create(
            nameof(BorderColor),
            typeof(Color),
            typeof(MobileToolGrid),
            Material.Color.SecondaryVariant
        );
        
        public Color BorderColor
        {
            get => (Color)GetValue(BorderColorProperty);
            set => SetValue(BorderColorProperty, value);
        }

        private bool debounce = false;
        private async void ToolItem_Tapped(object sender, EventArgs e)
        {
            if (debounce)
                return;
            debounce = true;
            BeforeTap?.Invoke(this, EventArgs.Empty);
            try
            {
                
                if ((sender is Frame frame) && (frame.BindingContext is MobileToolItem item) && item.IsEnabled)
                {
                    frame.Scale = 0.5;
                    await frame.ScaleTo(1, 150);
                    item.DoTap();
                }                

            }
            catch (Exception err)
            {
                MobileLogging.Log(err,"MobileToolGrid");
            }

            AfterTap?.Invoke(this, EventArgs.Empty);
            debounce = false;
        }

        private void _viewModel_OnLayoutChanged(object sender, ToolGridLayoutChangedEventArgs args)
        {
            _flexgrid.RowDefinitions.Clear();
            for (int i=0; i< args.RowCount; i++)
                _flexgrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto});
            
            _flexgrid.ColumnDefinitions.Clear();
            for (int i=0; i< args.ColCount; i++)
                _flexgrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star});
            BindableLayout.SetItemsSource(_flexgrid, null);
            BindableLayout.SetItemsSource(_flexgrid, _viewModel.VisibleItems);
        }
        
    }
}