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

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

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

using DXLib.Utils;

namespace iStatVball3;

/*
 * Implements a simple control for selecting a small integer value with +/- stepper buttons. The control will be
 * presented in a modal popup. The supported numeric range is 0-99.
 */
public class DXNumericEditor
{
	/* Constants */
	private const double DefaultWd = 175;
	private const double DefaultHt = 150;
	
	/* Events */
	public Action<int> Selected { get; set; }
	public Action Cancelled { get; set; }

	/* Properties */
	public int Number { get => number; set => SetNumber( value ); }

	// Options MUST be set first
	public int MinValue { get; set; }
	public int MaxValue { get; set; }

	public bool ShouldPad { get; set; }
	public bool ShouldWrap { get; set; }

	/* Fields */
	private readonly DXGridLayout layout;
	private readonly DXLabel numberLbl;

	private readonly DXIconButton plusBtn;
	private readonly DXIconButton minusBtn;

	private DXPopup popup;

	// Underlying value
	private int number;

	/* Methods */
	public DXNumericEditor()
	{
		bool ios = DXDevice.IsIOS;

		// Master layout
		layout = new DXGridLayout
		{
			BackgroundColor = DXColors.Light3,

			Padding = 0,
			RowSpacing = 0,
			ColumnSpacing = 0,

			WidthRequest = DefaultWd,
			HeightRequest = DefaultHt,
			
			Horizontal = LayoutOptions.Fill,
			Vertical = LayoutOptions.Fill
		};

		// 3 rows
		layout.AddStarRow( 50 );		// +
		layout.AddStarRow( 50 );		// - 
		layout.AddFixedRow( 50 );		// OK

		// 2 columns
		layout.AddStarColumn( 60 );		// Number
		layout.AddStarColumn( 40 );		// +/-

		// Number
		numberLbl = new DXLabel
		{
			TextColor = DXColors.Dark1,
			Font = DXFonts.OswaldBold,
			FontSize = 64,

			Margin = ios ? 0 : -10,
			VerticalTextAlignment = TextAlignment.Center,

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};

		layout.Add( numberLbl, 0, 0 );
		layout.SpanRows( numberLbl, 2 );

		// +/- background
		layout.Fill( DXColors.Light1, 1, 0, 1, 2 );

		// +
		plusBtn = new DXIconButton
		{
			Resource = "plus",
			IconColor = DXColors.Dark3,
			Size = 40,
			Margin = 0,
			
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.End,
			
			ButtonTapped = OnPlusTapped
		};

		layout.Add( plusBtn, 1, 0 );

		// -
		minusBtn = new DXIconButton
		{
			Resource = "minus",
			IconColor = DXColors.Dark3,
			Size = 40,
			Margin = 0,

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Start,

			ButtonTapped = OnMinusTapped
		};

		layout.Add( minusBtn, 1, 1 );

		// OK background
		layout.Fill( DXColors.Dark3, 0, 2, 2, 0 );

		// OK
		DXButton okBtn = new()
		{
			Resource = "alert.ok",
			Type = DXButton.ButtonType.Positive,

			ButtonWd = 50,
			ButtonHt = 35,
			Margin = 0,

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center,
			
			ButtonTapped = OnOkTapped,
		};

		okBtn.Init();
		
		layout.Add( okBtn, 0, 2 );
		layout.SpanColumns( okBtn, 2 );
	}

	// Used internally to set underlying numeric value
	private void SetNumber( int value )
	{
		number = value;
		numberLbl.Text = value.ToString( ShouldPad ? "00" : "0" );

		// Update button states
		plusBtn.IsDisabled = (number >= MaxValue) && !ShouldWrap;
		minusBtn.IsDisabled = (number <= MinValue) && !ShouldWrap;
	}

	// Displays editor in modal popup anchored to specified view
	public void Show( View view, double adjustX = 0, double adjustY = 0 )
	{
		popup = new DXPopup( null, layout )
		{
			ViewWidth = DefaultWd,
			ViewHeight = DefaultHt,
			
			PopupClosed = OnPopupClosed
		};

		popup.ShowFromView( view, adjustX, adjustY );
	}

	/* Event Callbacks */

	// Increment numeric value, optionally wrap
	private void OnPlusTapped()
	{
		Number = (number == MaxValue) ? (ShouldWrap ? MinValue : MaxValue) : (number + 1);
	}

	// Decrement numeric value, optionally wrap
	private void OnMinusTapped()
	{
		Number = (number == MinValue) ? (ShouldWrap ? MaxValue : MinValue) : (number - 1);
	}

	// User confirmed value selection
	private void OnOkTapped( object sender )
	{
		Selected?.Invoke( number );

		popup.Dismiss();
	}

	// User cancelled
	private void OnPopupClosed()
	{
		Cancelled?.Invoke();
	}
}

//
