/* 
 * 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.Alert;
using DXLib.UI.Control;
using DXLib.UI.Container;

using DXLib.Data;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Simple navigation stack used for the launch flow screens (landing, create account, and login). Also handles
 * transition to main UI.
 */ 
public class LaunchStack : DXContent
{
	/* Constants */

	// Max login data sync time (ms)
	private const int SyncTimeout = (60 * 1000);

	/* Properties */
	public int Count => pages.Count;
	public LaunchPage CurrentPage => (Count == 0) ? null : pages[ Count - 1 ];

	/* Fields */
	private readonly List<LaunchPage> pages;

	/* Methods */
	public LaunchStack()
	{
		BackgroundColor = DXColors.Dark1;

		Horizontal = LayoutOptions.Fill;
		Vertical = LayoutOptions.Fill;
		
		// Create container
		pages = [];
	}

	// Launches app to correct landing spot, either login flow or main UI
	public static async Task Launch()
	{
		Shell shell = Shell.Instance;

		// Check for cached login
		string uniqueId = DXPreferences.Get( "launch.user", null );
																														DXProfiler.Mark( "Launch" );		
		// No cache
		if ( uniqueId == null )
		{
            // Start in login flow
            shell.LaunchStack.Push( new LaunchLanding() );
			shell.ShowLaunch();

			// Device styling
			DXDevice.SetNavBarColor( DXColors.Dark1 );

			DXSpinner.Stop();
		}
		// Cached login
		else
		{
			// Device styling
			shell.SetStatusBarColor( AppBar.DefaultColor );
			shell.AppBar.IsVisible = true;
			
			bool timeout = false;

			// Enforce timeout for sync process
			DXTimer timer = DXTimer.Delay( SyncTimeout, () =>
			{
				timeout = true;
				HandleTimeout();
			});
																														DXProfiler.Mark( "Cached" );
			// Lookup user
			User user = await User.Read( uniqueId );
																														DXProfiler.Mark( "Read" );
			// Soonest UI has layout control
			shell.UpdateLayout();
			
            // Soonest spinner can start
            DXSpinner.Start( "login.sync" );

            // Perform login tasks
            await user.Login();
			
			// Start in main UI
			if ( !timeout )
			{
				timer.Stop();
																														DXProfiler.Mark( "Login" );
				await TransitionToMain( user );
			}
		}
	}

	// Navigates to destination after login or sync timeout
	public static void HandleTimeout()
	{
		DXAlert.ShowDestroy( "login.err", "login.err.sync", "account.logout", "login.retry", TransitionToLaunch, OnRetry );
	}

	// User retrying login/sync
	private static async void OnRetry()
	{
		await Launch();
	}

	// Returns to landing screen following login timeout or validation error
	public static void TransitionToLaunch()
	{
		// Delete cached login info
		User.Logout();

		DXSpinner.Stop();

		_ = Launch();
	}

	// Moves from launch UI to main UI, landing point depends on cache
	public static async Task TransitionToMain( User user )
	{
		Shell shell = Shell.Instance;
		
		// Provide global access to user
		Shell.CurrentUser = user;

		PageStack pages = shell.PageStack;

		// Done with Launch UI
		shell.HideLaunch();

		// Might have logged out
		pages.Clear();

		// See if user previously at Season Home or beyond
		string path = DXPreferences.Get( "launch.path", null );
		bool hasPath = (path != null);
																														DXProfiler.Mark( "Trans" );
		// Always at least have Org page
		OrganizationPage page = new( user );
		pages.Push( page, page.Title, false );
																														DXProfiler.Mark( "Org" );
		// Advancing past org
		if ( hasPath && DXData.HasConnection() )
		{
			string[] uniqueIds = path.Split( '|' );
		
			// Load each object along path
			Organization org = user.GetOrganization( uniqueIds[0] );
			Team team = org?.GetTeam( uniqueIds[1] );
			Season season = team?.GetSeason( uniqueIds[2] );
																														DXProfiler.Mark( "Path" );
			// Must populate below Season
			if ( season != null )
			{
				await season.PopulateFull();
			}
																			
			// Add pages along path to Season Home
			if ( org != null )
			{
				pages.Push( new TeamPage( org ), org.Name, false );
			}
			if ( team != null )
			{
				pages.Push( new SeasonPage( team ), team.Name, false );
			}
			if ( season != null )
			{
				pages.Push( new HomePage( season ), season.Name, false );
			}																											DXProfiler.Mark( "Pages", true );
																														
			// User may be in sample org tree
			Organization.SetScope( org );
		}

		// Main UI
		shell.ShowPageStack( true );																					DXProfiler.Mark( "Show" );
																			
		DXSpinner.Stop();
	}

	// Transitions back to login flow UI from main UI following a logout
	public static void TransitionFromMain()
	{
		Shell shell = Shell.Instance;

		// Remove main UI
		shell.HideAll();

		// Show launch UI
		shell.LaunchStack.Clear();
		shell.ShowLaunch();

		// Must occur AFTER show
		shell.LaunchStack.Push( new LaunchLanding() );
		shell.UpdateLayout();

		// Device styling
		shell.SetStatusBarColor( DXColors.Dark1 );
		DXDevice.SetNavBarColor( DXColors.Dark1 );
	}

	// Removes any pages currently on stack
	public void Clear()
	{
		pages.Clear();
	}

	// Pushes new page onto stack and displays it
	public void Push( LaunchPage page )
	{
		Shell shell = Shell.Instance;
		
		// Appbar used on create/login pages but not landing
		if ( Count > 0 )
		{
			AppBar appBar = shell.AppBar;

			appBar.HasBackButton = true;
			appBar.HasToolBar = false;
			appBar.IsVisible = true;

			// Device styling
			shell.SetStatusBarColor( AppBar.DefaultColor );
			DXDevice.SetNavBarColor( AppBar.DefaultColor );
		}

		pages.Add( page );

		// Display
		page.UpdateLayout();

		Content = page;

		shell.UpdateLayout();
	}

	// Removes top page from stack, shows page underneath
	public void Pop( bool show = true )
	{
		// Cannot pop last page
		if ( Count > 1 )
		{
			CurrentPage.Stop();
			pages.Remove( CurrentPage );

			// Allow stack change without updating display
			if ( show )
			{
				Content = CurrentPage;
				CurrentPage.Reset();
				
				bool landing = (Count == 1);

				// Landing does not have listener
				if ( !landing )
				{
					CurrentPage.Start();
				}
				
				Shell shell = Shell.Instance;
				shell.AppBar.IsVisible = !landing;

				Color color = landing ? DXColors.Dark1 : DXColors.Dark2;

				// Device styling
				shell.SetStatusBarColor( color );
				DXDevice.SetNavBarColor( color );
			}
		}
	}

	/* Layout */

	// Forces full UI redraw
	public override void UpdateLayout( LayoutType type )
	{
		// Account for mobile notch
		Padding = DXDevice.SafeAreaLRB();

		CurrentPage?.UpdateLayout( type );
	}
}

//
