using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Wino.Controls;
using Wino.Core.Domain.Models.Reader;
using Wino.Core.UWP.Controls;
using Wino.Helpers;

namespace Wino.MenuFlyouts
{
    public class FilterMenuFlyout : MenuFlyout
    {
        public static readonly DependencyProperty SelectedFilterChangedCommandProperty = DependencyProperty.Register(nameof(SelectedFilterChangedCommand), typeof(IRelayCommand<FilterOption>), typeof(FilterMenuFlyout), new PropertyMetadata(null));
        public static readonly DependencyProperty FilterOptionsProperty = DependencyProperty.Register(nameof(FilterOptions), typeof(List<FilterOption>), typeof(FilterMenuFlyout), new PropertyMetadata(null, new PropertyChangedCallback(OnOptionsChanged)));
        public static readonly DependencyProperty SelectedFilterOptionProperty = DependencyProperty.Register(nameof(SelectedFilterOption), typeof(FilterOption), typeof(FilterMenuFlyout), new PropertyMetadata(null, OnSelectedFilterOptionChanged));
        public static readonly DependencyProperty SelectedSortingOptionProperty = DependencyProperty.Register(nameof(SelectedSortingOption), typeof(SortingOption), typeof(FilterMenuFlyout), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedSortingOptionChanged)));
        public static readonly DependencyProperty SortingOptionsProperty = DependencyProperty.Register(nameof(SortingOptions), typeof(List<SortingOption>), typeof(FilterMenuFlyout), new PropertyMetadata(null, new PropertyChangedCallback(OnOptionsChanged)));
        public static readonly DependencyProperty SelectedSortingOptionChangedCommandProperty = DependencyProperty.Register(nameof(SelectedSortingOptionChangedCommand), typeof(IRelayCommand<SortingOption>), typeof(FilterMenuFlyout), new PropertyMetadata(null));

        public IRelayCommand<FilterOption> SelectedFilterChangedCommand
        {
            get { return (IRelayCommand<FilterOption>)GetValue(SelectedFilterChangedCommandProperty); }
            set { SetValue(SelectedFilterChangedCommandProperty, value); }
        }

        public IRelayCommand<SortingOption> SelectedSortingOptionChangedCommand
        {
            get { return (IRelayCommand<SortingOption>)GetValue(SelectedSortingOptionChangedCommandProperty); }
            set { SetValue(SelectedSortingOptionChangedCommandProperty, value); }
        }

        public List<FilterOption> FilterOptions
        {
            get { return (List<FilterOption>)GetValue(FilterOptionsProperty); }
            set { SetValue(FilterOptionsProperty, value); }
        }

        public List<SortingOption> SortingOptions
        {
            get { return (List<SortingOption>)GetValue(SortingOptionsProperty); }
            set { SetValue(SortingOptionsProperty, value); }
        }

        public FilterOption SelectedFilterOption
        {
            get { return (FilterOption)GetValue(SelectedFilterOptionProperty); }
            set { SetValue(SelectedFilterOptionProperty, value); }
        }

        public SortingOption SelectedSortingOption
        {
            get { return (SortingOption)GetValue(SelectedSortingOptionProperty); }
            set { SetValue(SelectedSortingOptionProperty, value); }
        }

        private static void OnSelectedFilterOptionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            if (obj is FilterMenuFlyout bar)
            {
                bar.SelectFilterOption(bar.SelectedFilterOption);
                bar.SelectedFilterChangedCommand?.Execute(bar.SelectedFilterOption);
            }
        }

        private static void OnSelectedSortingOptionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            if (obj is FilterMenuFlyout bar)
            {
                bar.SelectSortingOption(bar.SelectedSortingOption);
                bar.SelectedSortingOptionChangedCommand?.Execute(bar.SelectedSortingOption);
            }
        }

        private ToggleMenuFlyoutItem CreateFilterToggleButton(FilterOption option)
        {
            var button = new ToggleMenuFlyoutItem()
            {
                Text = option.Title,
                Tag = option,
                Icon = new WinoFontIcon() { Icon = XamlHelpers.GetWinoIconGlyph(option.Type) },
                IsChecked = option == SelectedFilterOption
            };

            button.Click += FilterToggleChecked;

            return button;
        }

        private ToggleMenuFlyoutItem CreateSortingToggleButton(SortingOption option)
        {
            var button = new ToggleMenuFlyoutItem()
            {
                Text = option.Title,
                Tag = option,
                Icon = new WinoFontIcon() { Icon = XamlHelpers.GetWinoIconGlyph(option.Type)},
                IsChecked = option == SelectedSortingOption
            };

            button.Click += SortingOptionChecked;

            return button;
        }

        private void SortingOptionChecked(object sender, RoutedEventArgs e)
        {
            if (sender is ToggleMenuFlyoutItem button)
            {
                button.IsHitTestVisible = false;

                var optionModel = button.Tag as SortingOption;

                SelectSortingOption(optionModel);
            }
        }



        private void FilterToggleChecked(object sender, RoutedEventArgs e)
        {
            if (sender is ToggleMenuFlyoutItem button)
            {
                button.IsHitTestVisible = false;

                var optionModel = button.Tag as FilterOption;

                SelectFilterOption(optionModel);
            }
        }

        private void SelectFilterOption(FilterOption option)
        {
            SelectedFilterOption = option;

            UncheckOtherFilterOptions();
        }

        private void SelectSortingOption(SortingOption option)
        {
            SelectedSortingOption = option;

            UncheckOtherSortingOptions();
        }

        private void UnregisterCheckedHandler(ToggleMenuFlyoutItem button)
        {
            button.Click -= FilterToggleChecked;
        }

        private void UncheckOtherFilterOptions()
        {
            if (Items.Any())
            {
                foreach (var item in Items)
                {
                    if (item is ToggleMenuFlyoutItem toggleButton && toggleButton.Tag is FilterOption option && option != SelectedFilterOption)
                    {
                        toggleButton.IsChecked = false;
                        toggleButton.IsHitTestVisible = true;
                    }
                }
            }
        }

        private void UncheckOtherSortingOptions()
        {
            if (Items.Any())
            {
                foreach (var item in Items)
                {
                    if (item is ToggleMenuFlyoutItem toggleButton && toggleButton.Tag is SortingOption option && option != SelectedSortingOption)
                    {
                        toggleButton.IsChecked = false;
                        toggleButton.IsHitTestVisible = true;
                    }
                }
            }
        }

        public void Dispose()
        {
            foreach (var item in Items)
            {
                if (item is ToggleMenuFlyoutItem toggleButton)
                {
                    UnregisterCheckedHandler(toggleButton);
                }
            }
        }

        private static void OnOptionsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            if (obj is FilterMenuFlyout bar && bar.SortingOptions != null && bar.FilterOptions != null)
            {
                bar.Dispose();

                bar.Items.Clear();

                if (bar.FilterOptions != null)
                {
                    foreach (var item in bar.FilterOptions)
                    {
                        bar.Items.Add(bar.CreateFilterToggleButton(item));
                    }
                }

                bar.Items.Add(new MenuFlyoutSeparator());

                // Sorting options.

                if (bar.SortingOptions != null)
                {
                    foreach (var item in bar.SortingOptions)
                    {
                        bar.Items.Add(bar.CreateSortingToggleButton(item));
                    }
                }
            }
        }
    }
}
