/*
 * Copyright (c)2009-2025 DemiVision, LLC. All Rights Reserved. The information
 * herein is the CONFIDENTIAL and PROPRIETARY information of DemiVision, LLC.
 */

using DXLib.UI.Layout;
using DXLib.UI.Container;

using DXLib.UI.Control.Button;
using DXLib.UI.Control.Checkbox;

using DXLib.Utils;

namespace DXLib.UI.Form.Control;

/*
 * A form control used to select multiple text items from a checkbox list. The items will be displayed in a popup view.
 */
public class DXMultiSelect : DXFormControl
{
	/* Constants */
	public const double DefaultPopupWd = 280;
	
	/* Properties */

	// LUT based
	public string Items { set => checkboxList.LoadItems( value ); }
	public IList<string> SelectedItems { set => SetSelectedItems( value ); }

	// Field values
	private string Text { get => entryBtn.Text; set => entryBtn.Text = value; }
	private Color TextColor { set => entryBtn.TextColor = value; }
	
	// Validation
	public int MaxSelections { get; set; }

	/* Fields */
	private readonly DXTextButton entryBtn;
	private readonly DXCheckboxList checkboxList;

	private readonly DXVerticalLayout popupLayout;
	private DXPopup popup;

	// Sizing
	private double popupHt;
	
	/* Methods */
	public DXMultiSelect()
	{
		// Form field
		entryBtn = new DXTextButton
		{
			Color = DXColors.Dark1,
			Font = DXFonts.Roboto,
			FontSize = 17,

			HeightRequest = 36,
			
			Horizontal = LayoutOptions.Fill,
			Vertical =  LayoutOptions.Fill,
			
			IsSticky = true,
			ButtonTapped = OnEntryTapped
		};
		
		// Popup view
		popupLayout = new DXVerticalLayout
		{
			Padding = new Thickness( 10, 15, 10, 10 ),
			Margin = 0,
			Spacing = 10,

			WidthRequest = DefaultPopupWd,
			
			Horizontal = LayoutOptions.Fill,
			Vertical = LayoutOptions.Fill
		};

		// Underlying controls
		checkboxList = new DXCheckboxList
		{
			IsTriState = false
		};

		popupLayout.Add( checkboxList );

		// Confirm button
		DXButton okBtn = new()
		{
			Resource = "alert.ok",
			Type = DXButton.ButtonType.Action,
			
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Start,
			
			ButtonTapped = OnCompleted
		};

		okBtn.Init();
		
		popupLayout.Add( okBtn );
	}

	// Populates checkbox list and form field
	private void SetSelectedItems( IList<string> keys )
	{
		checkboxList.SelectItems( keys );

		Text = checkboxList.GetKeyList();
		
		// Dynamically size popup
		popupHt = (checkboxList.GetViewHt() + popupLayout.Spacing + DXButton.DefaultHt + popupLayout.Padding.VerticalThickness);
 		popupLayout.HeightRequest = popupHt;
	}

	// Configures multiselect specific error hint text
	protected override void SetHintType( HintType type )
	{
		base.SetHintType( type );

		// Parent did not set
		if ( string.IsNullOrEmpty( hintLbl.Text ) )
		{
			string text = type switch
			{
				// 'Foo can have at most X values selected'
				HintType.RequiredMax => DXString.Get( "form.hint.multi.max", Title, MaxSelections ),
				
				_ => null
			};

			hintLbl.Text = text!;
		}
	}

	// Overrides default disabled opacity
	public override void SetDisabled( bool disabled )
	{
		base.SetDisabled( disabled );

		entryBtn.Opacity = 0.3;
	}
	
	// Returns list of values (not keys) from multiselect text line
	private List<string> GetValueList()
	{
		List<string> items = [];

		// Comma delimited
		if ( HasValue() )
		{
			items = Text.Split( DXCheckboxList.Separator ).ToList();
		}

		return items;
	}
	
	// Displays checkbox list in modal popup anchored to form control
	private void Show()
	{
		List<string> items = GetValueList();

		checkboxList.SelectItems( items );

		// Show popup
		popup = new DXPopup( Title, popupLayout )
		{
			AutoSize = true,
			PopupClosed = OnPopupClosed
		};
		
		popup.ShowFromView( this, (Width * 0.05), (popupLayout.Width * 0.50) );
	}

	// Resets form control button
	private void Reset()
	{
		if ( HasValue() )
		{
			entryBtn.Reset();
		}
	}
	
	/* Abstracts */

	// Insert in parent layout
	public override void Init()
	{
		AddControl( entryBtn );
	}

	// Returns underlying object as array of selected keys
	public override object GetObject()
	{
		return checkboxList.GetSelectedKeys();
	}

	// Placeholder only visible when not focused with no value
	public override void SetPlaceholder( bool focused )
	{
		bool hasValue = HasValue();

		// Focused never shows placeholder
		if ( focused )
		{
			Text = (hasValue ? Text : null)!;
			TextColor = DXColors.Dark1;
		}
		// Unfocused shows placeholder if no value
		else if ( !hasValue )
		{
			Text = Title;
			TextColor = DXColors.Dark4;
		}
	}

	// Has value if at least one item selected
	public override bool HasValue()
	{
		return !string.IsNullOrEmpty( Text ) && !Text.Equals( Title );
	}

	// Only valid if selected count within range
	public override bool IsValid()
	{
		return (!IsRequired && !HasValue()) || (checkboxList.SelectedCount() <= MaxSelections);
	}

	/* Event Callbacks */

	// User tapped anywhere on entry field
	private void OnEntryTapped( object data )
	{
		OnFocus();

		// Display in popup
		Show();
	}

	// Editing done
	private void OnCompleted( object sender )
	{
		OnChange();

		// Update field
		Text = checkboxList.GetKeyList();
		Reset();

		// Must occur last
		OnDone();

		popup.Dismiss();
	}
	
	// User dismissed popup
	private void OnPopupClosed()
	{
		Reset();
	}
}

//
