/* 
 * 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.Gestures;

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

using DXLib.Data;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Represents one row of stat buttons within a button area. Each row corresponds to one stat category. The category can
 * be modified by swiping across the row.
 */
public class ButtonRow : DXGridGestures
{
    /* Constants */
    private const double SwipeDistance = 30;
    private const double Pad = 7;

    /* Events */
    public Action<ButtonKey> ButtonTapped { get; set; }
	public Action RowPressed { get; set; }

    /* Properties */

	// Row eligible for swiping?
    public bool SwipeEnabled { get; set; }

	// Default/swipe configurations
	public ButtonConfig Config { get; set; }
	public ButtonConfig SwipeConfig { get; set; }

	/* Fields */
	private DXLabel titleLbl;
	private Dictionary<string,DXButton> buttons;

    // Swipe handling
    private bool swipeMode;
    private Point swipePt;

    /* Methods */
    public ButtonRow()
	{
		BackgroundColor = DXColors.Light4;

		// REQUIRED for mobile
		IgnoreSafeArea = true;
		
		Horizontal = LayoutOptions.Fill;
		Vertical = LayoutOptions.Fill;
		
		// Register for events
		Pressed = OnPressed;

		// Required for swipe
		Down += OnDown;
		Up += OnUp;
	}

	// Post construction initialization (same for all layouts)
	public void Init( bool swipe = false )
	{
		swipeMode = swipe;

		ButtonConfig config = swipeMode ? SwipeConfig : Config;

		bool ios = DXDevice.IsIOS;
		bool wide = DXDevice.IsTabletWide;
		bool large = DXDevice.IsLargeTablet();

		// Spacing
		Padding = new Thickness( Pad, 3, Pad, (Pad - 2) );

		RowSpacing = 3;
		ColumnSpacing = (Pad - 1);

		// Larger for large tablets
		double titleSize = (large && !wide) ? 12 : 10;

		// 2 rows, 1 column
		AddFixedRow( titleSize );	// Title
		AddStarRow();				// Buttons

		int count = config.Items.Count;

		// Title
		titleLbl = new DXLabel
		{
			Text = config.Title.ToUpper(),

			TextColor = config.Color,
			Font = DXFonts.RobotoBold,
			FontSize = titleSize,

			Margin = new Thickness( 0, (ios ? 0 : (wide ? -3 : -2)), 0, 0 )
		};

		Add( titleLbl, 0, 0, count, 1 );

		// Allocate container
		buttons = new Dictionary<string,DXButton>( count );

		double wd = (100.0 / count);

		// Last tapped button shown with darker color
		Color tapColor = config.Color.WithLuminosity( 0.3f );

		// 1 column for each button
		for ( int col = 0; col < count; col++ )
		{
			DXItem item = config.Items[ col ];
			string key = item.Key;

			// Create button
			DXButton button = new( false )
			{
				Text = item.Value,
				Data = key,

				ButtonColor = config.Color,
				FontSize = large ? 17 : 15,

				TapColor = tapColor,
				TapOpacity = 1.0,
				
				IsSticky = true,
				HasShadow = true,

				Horizontal = LayoutOptions.Fill,
				VerticalOptions = LayoutOptions.Fill,
					
				ButtonTapped = OnButtonTapped
			};

			button.Init();
			
			buttons.Add( key, button );

			// Equal width columns
			AddStarColumn( wd );
			Add( button, col, 1 );
		}
	}

	// Turns swipe mode on/off, updates title/color
	private void ToggleSwipe()
	{
        ClearAll();

        Init( !swipeMode );
    }

    /* Enable */

    // Enables title and all buttons in row
    public void EnableAll()
    {
	    titleLbl.Opacity = 1.0;

		foreach ( string key in buttons.Keys )
		{
			Enable( key );
		}
	}

	// Enables specified individual button
	public void Enable( string key )
	{
		buttons[ key ].IsDisabled = false;
	}

	/* Disable */

	// Disables title and all buttons in row
	public void DisableAll()
	{
		titleLbl.Opacity = DXButton.DefaultDisabledOpacity;
		
		foreach ( string key in buttons.Keys )
		{
			Disable( key );
		}
	}

	// Disables specified individual button
	public void Disable( string key )
	{
		buttons[ key ].IsDisabled = true;
	}

	/* Tap State */

	// Forces specified button into sticky tap state
	public void ShowTap( ButtonKey key )
	{
		buttons[ key.Key ].ShowTap();
	}

	// Resets sticky state of specified button
	public void ResetTap( ButtonKey key )
	{
		// Always revert to default
		if ( swipeMode )
		{
			ToggleSwipe();
		}

		buttons[ key.Key ].Reset();
	}

	/* Event Callbacks */

	// User tapped stat button, callback listener
	private void OnButtonTapped( DXButton button )
	{
        ButtonConfig config = swipeMode ? SwipeConfig : Config;

        ButtonTapped.Invoke( new ButtonKey
		{
			Category = config.Key,
			Key = (button.Data as string),

			IsRating = config.IsRating
		});
	}

	// User long pressed anywhere on row, callback listener
	private void OnPressed( Point point )
	{
		RowPressed?.Invoke();
	}

	// User tapped anywhere on row, tracks swipe
	private void OnDown( object sender, MR.Gestures.DownUpEventArgs args )
	{
		if ( SwipeEnabled )
		{
			swipePt = args.Touches[0];
		}
    }

	// User released tap, may result in swipe
    private void OnUp( object sender, MR.Gestures.DownUpEventArgs args )
	{
		if ( SwipeEnabled )
		{
			// Distance between tap and release point
			double distance = DXGraphics.Distance( swipePt, args.Touches[0] );

			// Traveled enough for swipe gesture
			if ( distance > SwipeDistance )
			{
				ToggleSwipe();
			}
		}
    }
}

//
