using System.Windows.Input;
using Connected.Annotations;
using Connected.Extensions;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

namespace Connected.Components;

public partial class ListItem : UIComponent, IDisposable
{
	protected string Classname =>
	new CssBuilder("list-item")
	  .AddClass("list-item-dense", (Dense ?? List?.Dense) ?? false)
	  .AddClass("list-item-gutters", !DisableGutters && !(List?.DisableGutters == true))
	  .AddClass("list-item-clickable", List?.Clickable)
	  .AddClass("ripple", List?.Clickable == true && !DisableRipple && !Disabled)
	  .AddClass($"selected-item mud-{List?.Color.ToDescription()}-text mud-{List?.Color.ToDescription()}-hover", _selected && !Disabled)
	  .AddClass("list-item-disabled", Disabled)
	  .AddClass(AdditionalClassList)
	.Build();

	[Inject] protected NavigationManager UriHelper { get; set; }

	[CascadingParameter] protected List List { get; set; }

	private bool _onClickHandlerPreventDefault = false;

	/// <summary>
	/// The text to display
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Behavior)]
	public string Text { get; set; }

	[Parameter]
	[Category(CategoryTypes.List.Selecting)]
	public object Value { get; set; }

	/// <summary>
	/// Avatar to use if set.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Behavior)]
	public string Avatar { get; set; }

	/// <summary>
	/// Link to a URL when clicked.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.ClickAction)]
	public string Href { get; set; }

	/// <summary>
	/// If true, force browser to redirect outside component router-space.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.ClickAction)]
	public bool ForceLoad { get; set; }

	/// <summary>
	/// Avatar CSS Class to apply if Avatar is set.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Appearance)]
	public string AvatarClass { get; set; }

	private bool _disabled;
	/// <summary>
	/// If true, will disable the list item if it has onclick.
	/// The value can be overridden by the parent list.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Behavior)]
	public bool Disabled
	{
		get => _disabled || (List?.Disabled ?? false);
		set => _disabled = value;
	}

	/// <summary>
	/// If true, disables ripple effect.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Appearance)]
	public bool DisableRipple { get; set; }

	/// <summary>
	/// Glyph to use if set.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Behavior)]
	public string Icon { get; set; }

	/// <summary>
	/// The color of the icon.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Appearance)]
	public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;

	/// <summary>
	/// Sets the Glyph Size.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Appearance)]
	public Size IconSize { get; set; } = Size.Medium;

	/// <summary>
	/// The color of the adornment if used. It supports the theme colors.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Expanding)]
	public ThemeColor AdornmentColor { get; set; } = ThemeColor.Default;

	/// <summary>
	/// Custom expand less icon.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Expanding)]
	public string ExpandLessIcon { get; set; } = Icons.Material.Filled.ExpandLess;

	/// <summary>
	/// Custom expand more icon.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Expanding)]
	public string ExpandMoreIcon { get; set; } = Icons.Material.Filled.ExpandMore;

	/// <summary>
	/// If true, the List Subheader will be indented.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Appearance)]
	public bool Inset { get; set; }

	/// <summary>
	/// If true, compact vertical padding will be used.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Appearance)]
	public bool? Dense { get; set; }

	/// <summary>
	/// If true, the left and right padding is removed.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Appearance)]
	public bool DisableGutters { get; set; }

	/// <summary>
	/// Expand or collapse nested list. Two-way bindable. Note: if you directly set this to
	/// true or false (instead of using two-way binding) it will force the nested list's expansion state.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Expanding)]
	public bool Expanded
	{
		get => _expanded;
		set
		{
			if (_expanded == value)
				return;
			_expanded = value;
			_ = ExpandedChanged.InvokeAsync(value);
		}
	}

	private bool _expanded;

	[Parameter]
	public EventCallback<bool> ExpandedChanged { get; set; }

	/// <summary>
	/// If true, expands the nested list on first display
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Expanding)]
	public bool InitiallyExpanded { get; set; }

	/// <summary>
	/// Command parameter.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.ClickAction)]
	public object CommandParameter { get; set; }

	/// <summary>
	/// Command executed when the user clicks on an element.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.ClickAction)]
	public ICommand Command { get; set; }

	/// <summary>
	/// Display content of this list item. If set, this overrides Text
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Behavior)]
	public RenderFragment ChildContent { get; set; }

	[Parameter]
	[Category(CategoryTypes.List.Behavior)]
	public bool OnClickHandlerPreventDefault
	{
		get => _onClickHandlerPreventDefault;
		set => _onClickHandlerPreventDefault = value;
	}

	/// <summary>
	/// Add child list items here to create a nested list.
	/// </summary>
	[Parameter]
	[Category(CategoryTypes.List.Behavior)]
	public RenderFragment NestedList { get; set; }

	/// <summary>
	/// List click event.
	/// </summary>
	[Parameter]
	public EventCallback<MouseEventArgs> OnClick { get; set; }

	protected void OnClickHandler(MouseEventArgs ev)
	{
		if (Disabled)
			return;
		if (!_onClickHandlerPreventDefault)
		{
			if (NestedList != null)
			{
				Expanded = !Expanded;
			}
			else if (Href != null)
			{
				List?.SetSelectedValue(this.Value);
				OnClick.InvokeAsync(ev);
				UriHelper.NavigateTo(Href, ForceLoad);
			}
			else
			{
				List?.SetSelectedValue(this.Value);
				OnClick.InvokeAsync(ev);
				if (Command?.CanExecute(CommandParameter) ?? false)
				{
					Command.Execute(CommandParameter);
				}
			}
		}
		else
		{
			OnClick.InvokeAsync(ev);
		}
	}

	protected override void OnInitialized()
	{
		_expanded = InitiallyExpanded;
		if (List != null)
		{
			List.Register(this);
			OnListParametersChanged();
			List.ParametersChanged += OnListParametersChanged;
		}
	}

	private Typo _textTypo;
	private void OnListParametersChanged()
	{
		if ((Dense ?? List?.Dense) ?? false)
		{
			_textTypo = Typo.body2;
		}
		else if (!((Dense ?? List?.Dense) ?? false))
		{
			_textTypo = Typo.body1;
		}
		StateHasChanged();
	}

	private bool _selected;

	internal void SetSelected(bool selected)
	{
		if (Disabled)
			return;
		if (_selected == selected)
			return;
		_selected = selected;
		StateHasChanged();
	}

	public void Dispose()
	{
		try
		{
			if (List == null)
				return;
			List.ParametersChanged -= OnListParametersChanged;
			List.Unregister(this);
		}
		catch (Exception) { /*ignore*/ }
	}

}
