using Microsoft.AspNetCore.Components;
using System.Collections.ObjectModel;
using Connected.Models;
using System.Collections.Immutable;

namespace Connected.Components;

public partial class Dropdown<T> : InputBase, IAsyncDisposable
{
	[Parameter, EditorRequired]
	public ObservableCollection<T> Items { get; set; } = new ObservableCollection<T>();

	[Parameter]
	public RenderFragment<T>? OptionTemplate { get; set; }

	[Parameter]
	public RenderFragment<T>? SelectedValueTemplate { get; set; }

	[Parameter]
	public ObservableCollection<T> SelectedItems { get; set; } = new();

	[Parameter]
	public EventCallback<ObservableCollection<T>> SelectedItemsChanged { get; set; }

	[Parameter]
	public bool AllowMultiple { get; set; }

	private bool DropdownOpen { get; set; }

	private bool IsItemSelected(T item)
	{
		return SelectedItems.Contains(item);
	}

	public void Open()
	{
		DropdownOpen = true;
	}

	public void Close()
	{
		DropdownOpen = false;
	}

	public void Toggle()
	{
		DropdownOpen = !DropdownOpen;
	}

	protected override void OnInitialized()
	{
		base.OnInitialized();
		
		OptionTemplate ??= (T item) => (builder) =>
		{
			builder.OpenElement(0, "div");
			builder.SetKey(item);
			builder.AddContent(1, item?.ToString());
			builder.CloseElement();
		};

		SelectedValueTemplate ??= (T item) => (builder) =>
		{
			builder.OpenElement(0, "span");
			builder.SetKey(item);
			builder.AddContent(1, item?.ToString());
			builder.CloseElement();
		};
	}
	protected override void OnParametersSet()
	{
		base.OnParametersSet();

		Items.CollectionChanged += CollectionChanged;
		SelectedItems.CollectionChanged += CollectionChanged;
	}

	private void CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
	{
		if (sender == SelectedItems)
			SelectedItemsChanged.InvokeAsync(SelectedItems);

		StateHasChanged();
	}

	private async Task OptionSelected(T item)
	{
		if (AllowMultiple)
		{
			if (SelectedItems.Contains(item))
			{
				SelectedItems.Remove(item);
				return;
			}
		}
		else
		{
			SelectedItems.Clear();
		}

		SelectedItems.Add(item);
	}

	public async ValueTask DisposeAsync()
	{
		Items.CollectionChanged -= CollectionChanged;
		SelectedItems.CollectionChanged -= CollectionChanged;
	}
}