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

using Syncfusion.Maui.Inputs;

using DXLib.UI.Layout;
using DXLib.UI.Control;

using DXLib.Utils;

namespace DXLib.UI.Form.Control;

/*
 * Numeric entry control where input is restricted within a typically small range (~10) and changes are only possible
 * through increment/decrement (+/-) buttons.
 */
public class DXStepper : DXFormControl
{
	/* Events */
	public Action NumberChanged { get; set; }
	public Action<DXStepper> ControlTapped { get; set; }

	/* Properties */
	public int Number { get => Convert.ToInt32( stepper.Value ); set => SetNumber( value ); }
	public int Step { set => SetNumber( value ); }

	public int MinValue { set => stepper.Minimum = value; }
	public int MaxValue { set => stepper.Maximum = value; }

	public bool IsLooping { set => stepper.AutoReverse = value; }
	public bool IsPlusMinus { set => Format = value ? "+#;-#;0" : "N0"; }

	public string Format { set => stepper.CustomFormat = value; }

	/* Fields */
	private readonly SfNumericEntry stepper;
	private bool ignoreTap;

	/* Methods */
	public DXStepper()
	{
		Padding = 0;
		Margin = 0;

		// Custom up/down buttons
		DXGridLayout plusBtn = CreateButton( "plus.png" );
		DXGridLayout minusBtn = CreateButton( "minus.png" );

		// Underlying control
		stepper = new SfNumericEntry
		{
			Padding = 0,
			Margin = new Thickness( (LeftMargin - 2), 0, 0, 0 ),

			HorizontalOptions = LayoutOptions.Fill,
			VerticalOptions = LayoutOptions.End,

			IsEditable = false,
			ShowBorder = false,
			
			UpDownOrder = UpDownOrder.DownThenUp,
			UpDownPlacementMode = NumericEntryUpDownPlacementMode.Inline,
			UpDownButtonColor = DXColors.Dark2,

			ValueChangeMode = ValueChangeMode.OnKeyFocus,
			CustomFormat = "n0",
			AllowNull = false,

			BackgroundColor = DXColors.Light4,
			TextColor = DXColors.Dark1,
			PlaceholderColor = DXColors.Dark4,

			FontFamily = DXFonts.Roboto,
			FontAttributes = FontAttributes.None,
			FontSize = 17,

            // Custom up/down buttons
            UpButtonTemplate = new DataTemplate( () => plusBtn ),
			DownButtonTemplate = new DataTemplate( () => minusBtn ),
		};

		// Register for events
		stepper.ValueChanged += OnValueChanged;

		Tapped += OnTapped;

		// Defaults
		MinValue = 0;
		MaxValue = 0;

		IsLooping = false;
		IsPlusMinus = false;
	}

	// Used internally to create custom up/down buttons
	private static DXGridLayout CreateButton( string resource )
	{
		const double size = 26;

		// WORKAROUND: custom icons must be nested in layout on Android
        DXGridLayout layout = new()
        {
            Padding = 0,
            Margin = 0,

            WidthRequest = size,
            HeightRequest = size,

            HorizontalOptions = LayoutOptions.Fill,
            VerticalOptions = LayoutOptions.Fill
        };

		// Icon
        DXIcon icon = new()
		{
			Resource = resource,
			
			Color = DXColors.Dark4,
            Aspect = Aspect.AspectFit,

            // Support transparency
            BackgroundColor = DXColors.Transparent,
            IsOpaque = false,

            Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};
		
		icon.SetSize( size );
		layout.Add( icon );

		return layout;
	}
	
	// Programmatically sets stepper value without invoking callback 
	private void SetNumber( int number )
	{
		stepper.ValueChanged -= OnValueChanged;

		// Set value
		stepper.Value = number;
		
		stepper.ValueChanged += OnValueChanged;
	}
	
	// Sets control specific colors
	public override void SetColor( Color color )
	{
		base.SetColor( color );
	
		stepper.BackgroundColor = color;
	}

	// Disables all extended controls
	public override void SetDisabled( bool disabled )
	{
		base.SetDisabled( disabled );

		// Disable stepper specific controls
		stepper.Opacity = disabled ? DisabledOpacity : 1.0;
	}

	/* Abstracts */

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

	// Returns current stepper value as integer
	public override object GetObject()
	{
		return stepper.Value;
	}

	// Sets stepper watermark text
	public override void SetPlaceholder( bool focused )
	{
		stepper.Placeholder = Title;
	}

	// Should always have value
	public override bool HasValue()
	{
		return (stepper.Value != null);
	}

	// Should always be valid, control validates
	public override bool IsValid()
	{
		return true;
	}

	/* Event Callbacks */

	// Only available event callback for underlying control
	private void OnValueChanged( object sender, NumericEntryValueChangedEventArgs args )
	{
		ignoreTap = true;

		OnFocus();
		OnChange();

		NumberChanged?.Invoke();
	}

	// User tapped anywhere in control, callback listener
	private void OnTapped( object sender, MR.Gestures.TapEventArgs args )
	{
		// Exclude +/- buttons
		if ( !ignoreTap )
		{
			ControlTapped?.Invoke( this );
		}

		ignoreTap = false;
	}
}

//
