using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using JetBrains.Annotations;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace InABox.Mobile
{

    public enum MobileTabStripItemLayout
    {
        TextOnly,
        ImageOnly,
        Vertical,
        Horizontal
    }

    public class MobileTabStripDataTemplateSelector : DataTemplateSelector
    {
        
        public MobileTabStripItemLayout SelectedLayout { get; set; }
        
        public DataTemplate VerticalTemplate { get; set; }
        public DataTemplate HorizontalTemplate { get; set; }
        public DataTemplate TextOnlyTemplate { get; set; }
        public DataTemplate ImageOnlyTemplate { get; set; }

        protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
        {
            return SelectedLayout switch
            {
                MobileTabStripItemLayout.ImageOnly => ImageOnlyTemplate,
                MobileTabStripItemLayout.Vertical => VerticalTemplate,
                MobileTabStripItemLayout.Horizontal => HorizontalTemplate,
                _ => TextOnlyTemplate
            };
        }
    }
    
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MobileTabStrip
    {

        public static readonly BindableProperty SelectedBackgroundProperty = BindableProperty.Create(
            nameof(SelectedBackground),
            typeof(Color),
            typeof(MobileTabStrip),
            XF.Material.Forms.Material.Color.Surface);
        
        public Color SelectedBackground
        {
            get => (Color)GetValue(SelectedBackgroundProperty);
            set => SetValue(SelectedBackgroundProperty, value);
        }
        
        public static readonly BindableProperty SelectedForegroundProperty = BindableProperty.Create(
            nameof(SelectedForeground),
            typeof(Color),
            typeof(MobileTabStrip),
            XF.Material.Forms.Material.Color.OnSurface);

        [TypeConverter(typeof(ColorTypeConverter))]
        public Color SelectedForeground
        {
            get => (Color)GetValue(SelectedForegroundProperty);
            set => SetValue(SelectedForegroundProperty, value);
        }
        
        public static readonly BindableProperty UnselectedBackgroundProperty = BindableProperty.Create(
            nameof(UnselectedBackground),
            typeof(Color),
            typeof(MobileTabStrip),
            XF.Material.Forms.Material.Color.Primary);

        [TypeConverter(typeof(ColorTypeConverter))]
        public Color UnselectedBackground
        {
            get => (Color)GetValue(UnselectedBackgroundProperty);
            set => SetValue(UnselectedBackgroundProperty, value);
        }
        
        public static readonly BindableProperty UnselectedForegroundProperty = BindableProperty.Create(
            nameof(UnselectedForeground),
            typeof(Color),
            typeof(MobileTabStrip),
            XF.Material.Forms.Material.Color.OnPrimary);

        [TypeConverter(typeof(ColorTypeConverter))]
        public Color UnselectedForeground
        {
            get => (Color)GetValue(UnselectedForegroundProperty);
            set => SetValue(UnselectedForegroundProperty, value);
        }
        
        // private readonly BindableProperty SeparatorColorProperty = BindableProperty.Create(
        //     nameof(SeparatorColor),
        //     typeof(Color),
        //     typeof(MobileTabStrip),
        //     XF.Material.Forms.Material.Color.Primary);
        //
        // public Color SeparatorColor
        // {
        //     get => (Color)GetValue(SeparatorColorProperty);
        //     set => SetValue(SeparatorColorProperty, value);
        // }
        
        public static readonly BindableProperty BorderColorProperty = BindableProperty.Create(
            nameof(BorderColor),
            typeof(Color),
            typeof(MobileTabStrip),
            XF.Material.Forms.Material.Color.Primary);
        
        public Color BorderColor
        {
            get => (Color)GetValue(BorderColorProperty);
            set => SetValue(BorderColorProperty, value);
        }
        
        public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(
            nameof(CornerRadius),
            typeof(float),
            typeof(MobileTabStrip),
            5f);

        public float CornerRadius
        {
            get => (float)GetValue(CornerRadiusProperty);
            set => SetValue(CornerRadiusProperty, value);
        }
        
        public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(
            nameof(FontSize),
            typeof(double),
            typeof(MobileTabStrip),
            Device.GetNamedSize(NamedSize.Small, typeof(Label)));

        [TypeConverter(typeof(FontSizeConverter))]
        public double FontSize
        {
            get => (double)GetValue(FontSizeProperty);
            set => SetValue(FontSizeProperty, value);
        }
        
        public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create(
            nameof(FontAttributes),
            typeof(FontAttributes),
            typeof(MobileTabStrip),
            FontAttributes.None);

        public FontAttributes FontAttributes
        {
            get => (FontAttributes)GetValue(FontAttributesProperty);
            set => SetValue(FontAttributesProperty, value);
        }
        
        public static readonly BindableProperty ItemsLayoutProperty = BindableProperty.Create(
            nameof(ItemsLayout),
            typeof(MobileTabStripItemLayout),
            typeof(MobileTabStrip),
            MobileTabStripItemLayout.TextOnly);

        public MobileTabStripItemLayout ItemsLayout
        {
            get => (MobileTabStripItemLayout)GetValue(ItemsLayoutProperty);
            set
            {
                _mobileTabStripDataTemplateSelector.SelectedLayout = value;
                SetValue(ItemsLayoutProperty, value);
            }
        }
        
        public static readonly BindableProperty ImageSizeProperty = BindableProperty.Create(
            nameof(ImageSize),
            typeof(Size),
            typeof(MobileTabStrip),
            new Size(30,30));

        public Size ImageSize
        {
            get => (Size)GetValue(ImageSizeProperty);
            set => SetValue(ImageSizeProperty, value);
        }
        
        public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create(
            nameof(SelectedIndex),
            typeof(int),
            typeof(MobileTabStrip),
            -1);
        
        public int SelectedIndex
        {
            get => (int)GetValue(SelectedIndexProperty);
            set => SelectItem((value > -1) && (value < Items.Count) ? Items[value] : null); 
        }
        
        public MobileTabStripItem SelectedItem 
        {
            get => Items.FirstOrDefault(x => x.Selected);
            set => SelectItem(value);
            
        }

        private void SelectItem(MobileTabStripItem value)
        {
            foreach (var item in Items)
                item.Selected = item == value;
            SetValue(SelectedIndexProperty,SelectedItem?.Index ?? -1);
            OnPropertyChanged(nameof(SelectedIndex));
            OnPropertyChanged(nameof(SelectedItem));
        }

        public event EventHandler SelectionChanged;
        
        public IList<MobileTabStripItem> Items { get; private set; }
        
        public MobileTabStrip()
        {
            HeightRequest = 50;
            
            var items = new ObservableCollection<MobileTabStripItem>();
            items.CollectionChanged += ItemsChanged;
            Items = items;
            
            InitializeComponent();
            BindableLayout.SetItemsSource(_grid, Items);
            
        }

        private void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            _grid.ColumnDefinitions.Clear();
            foreach (var item in Items)
            {
                item.Index = _grid.ColumnDefinitions.Count;
                _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
            }
            Device.BeginInvokeOnMainThread(() =>
            {
                SelectedItem ??= Items.FirstOrDefault();
            });
        }
        
        private void DoTap(object sender, EventArgs e)
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                SelectedItem = (sender as BindableObject)?.BindingContext as MobileTabStripItem;
                SelectionChanged?.Invoke(this,EventArgs.Empty);
            });

        }
    }
}