using Billing.Languages;
using Billing.Models;
using Billing.Themes;
using Billing.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Forms;

namespace Billing.Views
{
    public partial class CategorySelectPage : BillingPage
    {
        private static readonly BindableProperty TopCategoriesProperty = BindableProperty.Create(nameof(TopCategories), typeof(List<CategoryGrouping>), typeof(CategorySelectPage));
        private static readonly BindableProperty SubCategoriesProperty = BindableProperty.Create(nameof(SubCategories), typeof(List<UICategory>), typeof(CategorySelectPage));

        public List<CategoryGrouping> TopCategories
        {
            get => (List<CategoryGrouping>)GetValue(TopCategoriesProperty);
            set => SetValue(TopCategoriesProperty, value);
        }
        public List<UICategory> SubCategories
        {
            get => (List<UICategory>)GetValue(SubCategoriesProperty);
            set => SetValue(SubCategoriesProperty, value);
        }

        public Command TapTopCategory { get; }
        public Command TapSubCategory { get; }

        public event EventHandler<UICategory> CategoryTapped;

        private readonly int categoryId;
        private readonly Color defaultColor;

        public CategorySelectPage(int id)
        {
            categoryId = id;
            defaultColor = BaseTheme.CurrentPrimaryColor;
            TapTopCategory = new Command(OnTopCategoryTapped);
            TapSubCategory = new Command(OnSubCategoryTapped);

            TopCategories = new List<CategoryGrouping>
            {
                new(Resource.Spending, App.Categories.Where(c => c.Type == CategoryType.Spending && c.ParentId == null).Select(c => WrapCategory(c))),
                new(Resource.Income, App.Categories.Where(c => c.Type == CategoryType.Income && c.ParentId == null).Select(c => WrapCategory(c)))
            };

            UICategory cat;
            var category = App.Categories.FirstOrDefault(c => c.Id == categoryId);
            if (category == null)
            {
                cat = TopCategories.Where(g => g.Count > 0).Select(g => g.First()).FirstOrDefault();
            }
            else if (category.ParentId == null)
            {
                cat = TopCategories.SelectMany(g => g).FirstOrDefault(c => c.Category == category);
            }
            else
            {
                cat = TopCategories.SelectMany(g => g).FirstOrDefault(c => c.Category.Id == category.ParentId);
            }
            DoRefreshSubCategories(cat);

            InitializeComponent();
        }

        private UICategory WrapCategory(Category c)
        {
            return new UICategory(c)
            {
                IsChecked = c.Id == categoryId,
                Icon = c.Icon,
                Name = c.Name,
                TintColor = c.TintColor == Color.Transparent || c.TintColor == default ? defaultColor : c.TintColor
            };
        }

        private void DoRefreshSubCategories(UICategory category)
        {
            var many = TopCategories.SelectMany(g => g);
            foreach (var m in many)
            {
                m.IsChecked = m == category;
            }
            SubCategories = App.Categories.Where(c => c.ParentId == category.Category.Id).Select(c => WrapCategory(c)).ToList();
        }

        private async void OnTopCategoryTapped(object o)
        {
            if (Tap.IsBusy)
            {
                return;
            }
            using (Tap.Start())
            {
                if (o is UICategory category)
                {
                    DoRefreshSubCategories(category);
                    if (SubCategories.Count == 0)
                    {
                        CategoryTapped?.Invoke(this, category);
                        await Navigation.PopAsync();
                    }
                }
            }
        }

        private async void OnSubCategoryTapped(object o)
        {
            if (Tap.IsBusy)
            {
                return;
            }
            using (Tap.Start())
            {
                if (o is UICategory category)
                {
                    CategoryTapped?.Invoke(this, category);
                    await Navigation.PopAsync();
                }
            }
        }
    }
}