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

using Syncfusion.Maui.Popup;
using Syncfusion.Maui.ProgressBar;

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

using DXLib.Utils;

namespace DXLib.UI.Control;

/*
 * Implements a circular, indeterminate progress spinner. The spinner is modal, preventing user interaction until the
 * spinner is stopped. A text message can optionally be shown below the spinner, and a translucent overlay can optionally
 * be displayed in the background. The text message is tappable and can be used for cancel functionality.
 */
public static class DXSpinner
{
	/* Constants */
	private const double DefaultSize = 200;
	
	/* Fields */
	private static SfPopup instance;
	private static SfCircularProgressBar spinner;

	private static DXVerticalLayout layout;
	private static DXTextButton messageBtn;

	// Message tap callback (cancel)
	private static Action tapAction;
	
	/* Methods */
	
	// Starts indeterminate spinner with optional text message and translucent overlay
	public static void Start( string message = null, bool overlay = false, Action action = null )
	{
		tapAction = action;
		
		// Once-only lazy instantiation
		instance ??= Create();

		// Optional text
		UpdateMessage( message );

		// Optional translucent overlay
		instance.ShowOverlayAlways = overlay;
		
		// Start spinning
		spinner.IndeterminateAnimationDuration = 1000;

		// Show popup
		instance.Show();
	}

	// Stops spinner, hides overlay/popup
	public static void Stop()
	{
		if ( instance != null )
		{
			instance.IsOpen = false;
		}

		spinner.IndeterminateAnimationDuration = 0;
	}

	// Allows text message to be dynamically changed
	public static void UpdateMessage( string message )
	{
		messageBtn.Text = DXString.Get( message );

		// Do not take up layout space if no label
		if ( string.IsNullOrEmpty( message ) )
		{
			layout.Remove( messageBtn );
		}
		else
		{
			try
			{
				layout.Add( messageBtn );
			} 
			catch ( Exception )
			{
				layout.Remove( messageBtn );
			}
		}
	}
	
	// Creates singleton spinner popup
	private static SfPopup Create()
	{
		SfPopup popup = new()
		{
			Padding = 0,
			Margin = 0,
			
			// Modal with translucent overlay
			StaysOpen = true,
			ShowOverlayAlways = false,
			IsFullScreen = false,

			// Configure popup
			ShowHeader = false,
			ShowFooter = false,
			ShowCloseButton = false,

			// No animation
			AnimationMode = PopupAnimationMode.None,

			// Sizing
			WidthRequest = DefaultSize,
			HeightRequest = DefaultSize,
			
			// Styling
			PopupStyle = new PopupStyle
			{
				CornerRadius = 0,
				HasShadow = false,
				StrokeThickness = 0,

				PopupBackground = Colors.Transparent,
				OverlayColor = Color.FromArgb( "#55000000" )
			}
		};

		// Spinner/text layout
		layout = new DXVerticalLayout
		{
			BackgroundColor = DXColors.Transparent,
			
			Padding = 0,
			Margin = new Thickness( 0, DXDevice.GetSafeTop(), 0, 0 ),
			Spacing = 5,
			
			WidthRequest = DefaultSize,
			HeightRequest = DefaultSize,
			
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};
		
		double spinnerSize = DXDevice.IsTablet ? 80 : 65;
		
		// Spinner (on translucent track, centered on screen)
		spinner = new SfCircularProgressBar
		{
			IsIndeterminate = true,
			
			BackgroundColor = Colors.Transparent,
			ProgressFill = DXColors.Negative,
			TrackFill = DXColors.ColorWithAlpha( DXColors.Negative, 0.5 ),

			ThicknessUnit = SizeUnit.Pixel,
			TrackThickness = 8,
			ProgressThickness = 8,

			IndeterminateAnimationEasing = Easing.Linear,
			IndeterminateAnimationDuration = 0,

			HeightRequest = spinnerSize,
			WidthRequest = spinnerSize,

			HorizontalOptions = LayoutOptions.Center
		};
		
		layout.Add( spinner );
		
		// Progress message
		messageBtn = new DXTextButton
		{
			TextColor = DXColors.Light4,
			Font = DXFonts.RobotoBold,
			FontSize = 17,

			LineBreakMode = LineBreakMode.NoWrap,
			Horizontal = LayoutOptions.Center,
			
			ButtonTapped = OnMessageTapped
		};
		
		// Set content
		popup.ContentTemplate = new DataTemplate( () => layout );

		return popup;
	}
	
	/* Event Callbacks */

	// User tapped message, callback listener
	private static void OnMessageTapped( object sender )
	{
		tapAction?.Invoke();		
	}
}

//
