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

using DXLib.Utils;

namespace iStatVball3;

/*
 * Toolbar containing Settings, Help, and Account buttons. Optionally also contains 1-2 Custom buttons. Managed by
 * parent AppBar or Record form. On smaller screens, buttons can be shown in 'More' popup menu.
 */
public class ToolBar : DXGridLayout
{
	/* Constants */
	public const double Pad = 5;

	private const int BaseCount = 3;
	private const int MaxCount = 5;

	private const double DefaultSpacing = 10;
	private const double MenuWd = 160;

	// Available display modes
	public enum DisplayMode
	{
		More,
		OneLine,
		TwoLine
	};
	
	/* Events */
	public Action Custom1Tapped { get; set; }
	public Action Custom2Tapped { get; set; }

	/* Properties */
	public DisplayMode Mode { get; set; }

	public bool IsMoreMode => Mode == DisplayMode.More;
	public bool IsTwoLine => Mode == DisplayMode.TwoLine;

	public double IconHt { get; set; }
	public double IconSize => IconHt + (Pad * 2);

	public double Spacing { get => ColumnSpacing; set => ColumnSpacing = value; }

	public bool HasCustom1 => Custom1Btn?.HasResource ?? false;
	public bool HasCustom2 => Custom2Btn?.HasResource ?? false;

	public bool HasCustom => HasCustom1 || HasCustom2;

	// External access for anchoring to buttons
	public DXIconButton MoreBtn { get; private set; }

	public DXIconButton Custom1Btn { get; private set; }
	public DXIconButton Custom2Btn { get; private set; }

	/* Fields */
	private readonly DXIconButton settingsBtn;
	private readonly DXIconButton helpBtn;
	private readonly DXIconButton accountBtn;

	// Mobile 'More' popup
	private readonly DXVerticalLayout moreMenu;
	private readonly DXPopup morePopup;

	// Currently open drawer
	private DXDrawer drawer;
	
	/* Methods */
	public ToolBar( bool sticky )
	{
		bool ios = DXDevice.IsIOS;

		Padding = 0;
		Margin = new Thickness( 0, 4, 0, 0 );

		RowSpacing = (DefaultSpacing - 1);
		ColumnSpacing = DefaultSpacing;

		Horizontal = LayoutOptions.End;
		Vertical = LayoutOptions.Center;
		
		// Defaults
		Mode = DisplayMode.OneLine;
		IconHt = 18;

		/* All buttons have extra padding to increase tap zone */

		// Height constant
		double size = IconSize;

		// Normal buttons
		settingsBtn = new DXIconButton
		{
			Padding = Pad,

			Resource = "settings",
			IconColor = DXColors.Light2,
			Size = size,

			IsSticky = sticky,
			ButtonTapped = OnSettingsTapped
		};
		
		helpBtn = new DXIconButton
		{
			Padding = Pad,

			Resource = DXDevice.IsTablet ? "help" : "help_mobile",
			IconColor = DXColors.Light2,
			Size = size,

			IsSticky = sticky,
			ButtonTapped = OnHelpTapped
		};
		
		accountBtn = new DXIconButton
		{
			Padding = Pad,

			Resource = "account",
			IconColor = DXColors.Light2,
			Size = size,

			IsSticky = sticky,
			ButtonTapped = OnAccountTapped
		};
		
		// Custom buttons (always blue, always sticky)
		Custom1Btn = new DXIconButton
		{
			Padding = Pad,
			
			IconColor = DXColors.Action,
			Size = (size + 2),

			IsSticky = true,
			ButtonTapped = OnCustom1Tapped
		};
		
		Custom2Btn = new DXIconButton
		{
			Padding = Pad,
			
			IconColor = DXColors.Action,
			Size = (size + 2),

			IsSticky = true,
			ButtonTapped = OnCustom2Tapped
		};
		
		// 'More' button used on mobile only
		if ( DXDevice.IsMobile )
		{
			MoreBtn = new DXIconButton
			{
				Padding = Pad,
				Vertical = LayoutOptions.End,

				Resource = "more",
				IconColor = DXColors.Light4,
				Size = size,

				IsSticky = true,
				ButtonTapped = OnMoreTapped
			};
			
			const double rowPad = (ToolBarItem.RowPad * 2);
			
			double spacing = (IconHt - rowPad);
			Thickness padding = new Thickness( 10, 10, 10, 10 );

			double menuHt = ((IconSize + rowPad) * BaseCount) + (spacing * (BaseCount - 1)) + padding.VerticalThickness - (ios ? 10 : 0);

			// 'More' popup menu
			moreMenu = new DXVerticalLayout
			{
				BackgroundColor = DXColors.Light4,

				Padding = padding,
				Spacing = spacing,
				
				WidthRequest = MenuWd,
				HeightRequest = menuHt,
				
				IgnoreSafeArea = true
			};
			
			// Add base items
			moreMenu.Add( new ToolBarItem { Icon = "settings", Resource = "toolbar.settings", ItemTapped = OnSettingsTapped } );
			moreMenu.Add( new ToolBarItem { Icon = "help", Resource = "toolbar.help", ItemTapped = OnHelpTapped } );
			moreMenu.Add( new ToolBarItem { Icon = "account", Resource = "toolbar.account", ItemTapped = OnAccountTapped } );

			morePopup = new DXPopup( moreMenu )
			{
				ViewWidth = MenuWd,
				ViewHeight = menuHt,
				
				PopupClosed = OnPopupClosed
			};
		}
	}

	/* Sizing */

	// Returns dynamic width of toolbar
	public double GetWidth()
	{
		return Mode switch
		{
			// More menu
			DisplayMode.More => IconSize,
			
			// Single row (fixed 5 wide)
			DisplayMode.OneLine => (IconSize * MaxCount) + (Spacing * (MaxCount - 1)),
			
			// Two rows (fixed 3 wide)
			DisplayMode.TwoLine => (IconSize * BaseCount) + (Spacing * (BaseCount - 1)),
			
			// NA
			_ => 0
		};
	}

	// Returns dynamic height of toolbar
	public double GetHeight()
	{
		return IsTwoLine ? ((IconSize * 2) + RowSpacing) : IconSize;
	}

	/* Custom */

	// Adds custom button to toolbar/menu
	public void AddCustom( int index, string icon, string text )
	{
		bool custom1 = (index == 1);
		bool custom2 = (index == 2);

		if ( DXDevice.IsMobile )
		{
			// More menu (always blue)
			if ( (custom1 && !HasCustom1) || (custom2 && !HasCustom2) )
			{
				bool ios = DXDevice.IsIOS;
				
				ToolBarItem item = new()
				{
					Icon = icon,
					Resource = text,
					Color = DXColors.Action,

					Margin = DXUtils.Top( -1 )
				};

				if ( custom1 )
				{
					item.ItemTapped = OnCustom1Tapped;
				}
				else
				{
					item.ItemTapped = OnCustom2Tapped;
				}

				double newHt = ((IconHt + (ToolBarItem.RowPad * 2)) + moreMenu.Spacing) + (ios ? 0 : 10);
				
				// Must increase menu/popup height
				moreMenu.HeightRequest += newHt;
				morePopup.ViewHeight += newHt;
				
				moreMenu.Insert( 0, item );
			}
		}

		// Toolbar
		DXIconButton btn = custom1 ? Custom1Btn : Custom2Btn;

		btn.Resource = icon;

		// MUST redraw entire app bar to resize
		Shell.Instance.AppBar.UpdateLayout();
	}

	// Removes custom button from toolbar/menu
	public void RemoveCustom( int index )
	{
		// More menu
		if ( DXDevice.IsMobile )
		{
			if ( moreMenu.Count > BaseCount )
			{
				moreMenu.RemoveAt( 0 );
				
				double oldHt = ((IconHt + (ToolBarItem.RowPad * 2)) + moreMenu.Spacing);

				// Reduce menu height
				moreMenu.HeightRequest -= oldHt;
				morePopup.ViewHeight -= oldHt;
			}
		}

		// Toolbar
		if ( HasCustom )
		{
			DXIconButton btn = (index == 1) ? Custom1Btn : Custom2Btn;

			btn.Resource = null;
			Remove( btn );

			Shell.Instance.AppBar.UpdateLayout();
		}
	}

	// Resets sticky state of all base buttons
	public void Reset()
	{
		settingsBtn.Reset();
		helpBtn.Reset();
		accountBtn.Reset();
	}

	// Resets custom button sticky state
	public void ResetCustom()
	{
		Custom1Btn.Reset();
		Custom2Btn.Reset();
	}

	/* Event Callbacks */

	// Open drawer with Settings content
	private void OnSettingsTapped()
	{
		morePopup?.Dismiss();

		// Create Settings drawer
		drawer = new DXDrawer();

		drawer.SetTitle( "settings.title" );
		drawer.SetView( new SettingsDrawer( drawer ) );
			
		drawer.Show();
	}

	// Open drawer with Help content
	private void OnHelpTapped()
	{
		morePopup?.Dismiss();

		// Create Help drawer
		drawer = new DXDrawer();
		
		drawer.SetTitle( "help.title" );
		drawer.SetView( new HelpDrawer( drawer ) );
			
		drawer.Show();
	}

	// Open drawer with Account info content
	private void OnAccountTapped()
	{
		morePopup?.Dismiss();

		// Create Account drawer
		drawer = new DXDrawer();
		
		drawer.SetTitle( "account.title" );
		drawer.SetView( new AccountDrawer( drawer ) );
			
		drawer.Show();
	}

	// Callback custom listener
	private void OnCustom1Tapped()
	{
		if ( IsMoreMode )
		{
			morePopup?.Dismiss();
		}

		Custom1Tapped?.Invoke();
	}

	// Callback custom listener
	private void OnCustom2Tapped()
	{
		if ( IsMoreMode )
		{
			morePopup?.Dismiss();
		}

		Custom2Tapped?.Invoke();
	}

	// Show 'More' popup menu
	private void OnMoreTapped()
	{
		morePopup.ShowFromView( MoreBtn );
	}

	// Reset more button
	private void OnPopupClosed()
	{
		MoreBtn.Reset();
	}

	/* Layout */

	// Drawers/menus do not rotate correctly, hide instead
	public void Rotate()
	{
		if ( drawer != null )
		{
			drawer.Hide();
			Reset();
		}

		if ( morePopup != null )
		{
			morePopup.Hide();
			MoreBtn.Reset();
		}
	}
	
	// Redraws toolbar/menu layout
	public override void UpdateLayout( LayoutType type )
	{
		ClearAll();

		// Could be toolbar or menu
		LayoutButtons();
	}

	// Arranges buttons based on device type/orientation
	private void LayoutButtons()
	{
		switch ( Mode )
		{
			// More
			case DisplayMode.More:
			{
				double wd = (HasCustom1 || HasCustom2) ? (MenuWd * 1.20) : MenuWd;
				
				moreMenu.WidthRequest = wd;
				morePopup.ViewWidth = wd;

				AddFixedColumn( IconSize );
				Add( MoreBtn, 0, 0 );
				break;
			}
			// 3-5 buttons on single line
			case DisplayMode.OneLine:
			{
				AddFixedColumns( MaxCount, IconSize );

				// Dynamically add custom button(s)
				if ( HasCustom2 )
				{
					Add( Custom2Btn, 0, 0 );
				}

				if ( HasCustom1 )
				{
					Add( Custom1Btn, 1, 0 );
				}

				// Base buttons
				Add( settingsBtn, 2, 0 );
				Add( helpBtn, 3, 0 );
				Add( accountBtn, 4, 0 );

				break;
			}
			// Buttons split across two lines
			case DisplayMode.TwoLine:
			{
				AddStarRows( 2 );
				AddFixedColumns( 3, IconSize );

				// Base buttons on top row
				Add( settingsBtn, 0, 0 );
				Add( helpBtn, 1, 0 );
				Add( accountBtn, 2, 0 );

				// Custom buttons second row (right aligned)
				if ( HasCustom2 )
				{
					Add( Custom2Btn, 1, 1 );
				}
				if ( HasCustom1 )
				{
					Add( Custom1Btn, 2, 1 );
				}

				break;
			}
			
			default: break;
		}
	}
}

//
