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

namespace Connected.Components;
public partial class SimpleSelect<ValueType> : InputBase
{
	private bool component_loaded = false;
	#region Parameters
	
	/// <summary>
	/// Value that is currently selected in the dropdown. Used for @bind-Value
	/// </summary>
	[Parameter]
	public ValueType? Value { get; set; }

	/// <summary>
	/// Collection of Items to work on (Filter). Filtered result is then shown in dropdown. If no filter is aplied, all the items are shown
	/// </summary>
	[Parameter, EditorRequired]
	public ObservableCollection<ValueType>? Items { get; set; }

	/// <summary>
	/// Collection of items from 'Items' filtered with 'SearchText'
	/// </summary>
	private List<ValueType>? FilteredItems { get; set; }

	/// <summary>
	/// Enable edit text search box for item filtering
	/// Options: true or false
	/// Default: true
	/// </summary>
	[Parameter]
	public bool EnableSearch { get; set; } = true;

	private string _searchText { get; set; } = string.Empty;

	/// <summary>
	/// Search string provided by user
	/// Options: any string
	/// Default: string.Empty
	/// </summary>
	public string SearchText
	{
		get
		{
			return _searchText;
		}
		set
		{
			_searchText = value;
			FilterItems();
		}
	}

	#endregion

	#region Events, Methods

	/// <summary>
	/// Method for setting the item on select
	/// </summary>
	/// <param name="item">item that will be set as selected</param>
	/// <returns>Methot returns nothing</returns>
	private async Task SetSelectedItem(ValueType item)
	{
		await ValueChanged.InvokeAsync(item);
	}

	/// <summary>
	/// Method for filtering items using 'SearchText' as filter
	/// </summary>
	private void FilterItems()
	{
		if (Items is not null)
		{
			if (string.IsNullOrEmpty(_searchText))
			{
				SetItems();
			}
			else
			{
				FilteredItems = Items.Where(item => item.ToString().ToLower().Contains(_searchText.ToLower())).ToList();
			}
			StateHasChanged();
		}
	}

	/// <summary>
	/// Event triggered when value changes
	/// </summary>
	[Parameter]
	public EventCallback<ValueType> ValueChanged { get; set; }


	/// <summary>
	/// Method for setting the FilteredItems collection keeping the original Item collection
	/// </summary>
	private void SetItems()
	{
		if (Items is not null)
		{
			FilteredItems = Items.ToList();
		}
	}

	/// <summary>
	/// Event triggered when the provided Items collection changes
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void OriginalItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
	{
		SetItems();
		FilterItems();
	}

	#endregion

	#region Lifecycle

	/// <summary>
	/// Initializing Collections and aplying Filters if provided
	/// </summary>
	/// <returns>Nothing gets returned</returns>
	protected override async Task OnInitializedAsync()
	{
		await base.OnInitializedAsync();
		if (Items is null)
		{
			Items= new ObservableCollection<ValueType>();
		}
		SetItems();
		if (_searchText.Length > 0)
			FilterItems();
		Items.CollectionChanged += OriginalItems_CollectionChanged;
		
		component_loaded = true;
		StateHasChanged();
	}

	#endregion

}