using static Blahblah.FlowerApp.Extensions;

namespace Blahblah.FlowerApp.Controls;

class ItemSelectorPage<K, T> : ContentPage where T : IdTextItem<K>
{
    public EventHandler<T>? Selected;

    public ItemSelectorPage(string title, T[] source, bool multiple = false, K[]? selected = null, string display = nameof(IdTextItem<K>.Text), string? detail = null)
    {
        Title = title;

        var itemsSource = source.Select(t => new SelectableItem<T>
        {
            Item = t,
            IsSelected = selected != null && selected.Contains(t.Id)
        }).ToArray();

        var list = new ListView
        {
            SelectionMode = ListViewSelectionMode.None,
            ItemsSource = itemsSource,
            ItemTemplate = new DataTemplate(() =>
            {
                var content = new Grid
                {
                    Margin = new Thickness(12, 0),
                    ColumnSpacing = 12,
                    ColumnDefinitions =
                    {
                        new(30),
                        new(GridLength.Star),
                        new(GridLength.Auto)
                    },
                    Children =
                    {
                        new SecondaryLabel
                        {
                            VerticalOptions = LayoutOptions.Center,
                            HorizontalOptions = LayoutOptions.Center,
                            Text = Res.Check,
                            FontFamily = "FontAwesome"
                        }
                        .Binding(IsVisibleProperty, nameof(SelectableItem<T>.IsSelected)),

                        new Label
                        {
                            VerticalOptions = LayoutOptions.Center
                        }
                        .Binding(Label.TextProperty, $"{nameof(SelectableItem<T>.Item)}.{display}")
                        .GridColumn(1)
                    }
                };
                if (detail != null)
                {
                    content.Children.Add(
                        new SecondaryLabel
                        {
                            VerticalOptions = LayoutOptions.Center
                        }
                        .Binding(Label.TextProperty, $"{nameof(SelectableItem<T>.Item)}.{detail}")
                        .GridColumn(2));
                }
                return new ViewCell
                {
                    View = content
                };
            })
        };

        list.ItemTapped += List_ItemTapped;

        Content = list;
    }

    private async void List_ItemTapped(object? sender, ItemTappedEventArgs e)
    {
        if (e.Item is SelectableItem<T> item)
        {
            Selected?.Invoke(this, item.Item);
            await Navigation.PopAsync();
        }
    }
}

class SelectableItem<T> : BindableObject
{
    public static BindableProperty IsSelectedProperty = CreateProperty<bool, SelectableItem<T>>(nameof(IsSelected));
    public static BindableProperty ItemProperty = CreateProperty<T, SelectableItem<T>>(nameof(Item));

    public bool IsSelected
    {
        get => (bool)GetValue(IsSelectedProperty);
        set => SetValue(IsSelectedProperty, value);
    }
    public T Item
    {
        get => (T)GetValue(ItemProperty);
        set => SetValue(ItemProperty, value);
    }
}

class IdTextItem<T> : BindableObject
{
    public static BindableProperty IdProperty = CreateProperty<T, IdTextItem<T>>(nameof(Id));
    public static BindableProperty TextProperty = CreateProperty<string, IdTextItem<T>>(nameof(Text));
    public static BindableProperty DetailProperty = CreateProperty<string?, IdTextItem<T>>(nameof(Detail));

    public T Id
    {
        get => (T)GetValue(IdProperty);
        set => SetValue(IdProperty, value);
    }
    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    }
    public string? Detail
    {
        get => (string?)GetValue(DetailProperty);
        set => SetValue(DetailProperty, value);
    }
}