/* 
 * 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;
using DXLib.UI.Control.Button;

using DXLib.Utils;

namespace DXLib.UI.Form.Control;

/*
 * A form control used to input multiple lines of alphanumeric text with basic validation. A truncated text value is shown
 * in the form control field while text entry occurs in a separate popup.
 */
public class DXEditorField : DXFormControl
{
	/* Properties */
	public string Text { get => textValue; set => UpdateText( value ); }

	public int MinLength { get; set; }
	public int MaxLength { get; set; }

	/* Fields */
	private readonly DXTextButton textBtn;
	
	private DXEditor editor;
	private DXPopup popup;
	
	// Current value
	private string textValue;

	/* Methods */
	public DXEditorField()
	{
		HasClear = false;
		MinLength = 0;

		// Control field
		textBtn = new DXTextButton
		{
			Color = DXColors.Dark1,
			
			Font = DXFonts.Roboto,
			FontSize = 17,
			
			LineBreakMode = LineBreakMode.TailTruncation,
			
			Horizontal = LayoutOptions.Fill,
			Vertical = LayoutOptions.Center,
	
			IsSticky = true,
			ButtonTapped = OnButtonTapped
		};

		// Register for events
		textBtn.Focused += OnFocused;
		textBtn.Unfocused += OnUnfocused;
	}

	// Updates internal text value, displays in control field
	private void UpdateText( string value )
	{
		textValue = value;
		
		textBtn.Text = value;
	}

	// Displays text editor, with OK button, in non-modal popup 
	private void ShowEditor()
	{
		// Layout
		DXGridLayout layout = new DXGridLayout
		{
			BackgroundColor = DXColors.Light4,
			
			Padding = 15,
			RowSpacing = 15,
			
			Horizontal = LayoutOptions.Fill,
			Vertical = LayoutOptions.Fill,
			
			IsClippedToBounds = true,
			IgnoreSafeArea = false
		};
		
		// Title, border, editor
		editor = new DXEditor
		{
			Text = textValue,

			Title = Title,
			Placeholder = DXString.Get( "form.text" ),
			
			MaxLength = MaxLength,
			LineCount = 12
		};
		
		// Confirm button
		DXButton okBtn = new()
		{
			Resource = "alert.ok",
			Type = DXButton.ButtonType.Action,
			
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Start,
			
			ButtonTapped = OnCompleted
		};

		okBtn.Init();

		// 1 column, 2 rows
		layout.AddStarRow();							// 0: editor
		layout.AddFixedRow( DXButton.DefaultHt );		// 1: button
		
		// Add components
		layout.Add( editor, 0, 0 );
		layout.Add( okBtn, 0, 1 );

		// Non-modal popup
		popup = new DXPopup
		{
			ViewWidth = 400,
			ViewHeight = 310,

			PopupClosed = OnDismissed
		};
		
		// No title
		popup.SetTitle( null );
		popup.SetContent( layout );
		
		// Anchor to form control
		popup.ShowFromView( textBtn );
	}

	/* Abstracts */

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

	// Returns underlying full text value
	public override object GetObject()
	{
		return textValue;
	}

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

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

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

		textBtn.Opacity = 0.4;
	}
	
	// Has value if text has been entered
	public override bool HasValue()
	{
		return !string.IsNullOrEmpty( textValue );
	}

	// Only valid if optional or minimum text entered
	public override bool IsValid()
	{
		return !IsRequired || (HasValue() && (textValue.Length >= MinLength));
	}

	/* Event Callbacks */

	// User tapped form control, show text editor
	private void OnButtonTapped( object sender )
	{
		ShowEditor();
	}

	// User completed text editing
	private void OnCompleted( object sender )
	{
		Text = editor.Text;
		
		popup.Hide();
		textBtn.Reset();
		
		SetPlaceholder( true );
		
		OnChange();
		OnDone();
	}
	
	// User tapped away from popup without saving
	private void OnDismissed()
	{
		textBtn.Reset();
		
		OnDone();
	}
	
	// Control gained focus
	private void OnFocused( object sender, FocusEventArgs args )
	{
		OnFocus();
	}

	// Control lost focus
	private void OnUnfocused( object sender, FocusEventArgs args )
	{
		OnUnfocus();
	}
}

//
