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

using DXLib.Utils;

namespace iStatVball3;

/*
 * Displays form overlay for an Analyze dashboard screen. A dashboard card is displayed for each metric category. There
 * is a separate list of dashboard cards for each team. Dashboard categories are organized into groups. Each dashboard
 * is configured via an external JSON file. 
 */ 
public class DashboardForm : DXGridLayout
{
	/* Properties */
	public static string Title => DXString.Get( "dashboard.title" );

	/* Fields */
	private DashboardTeam teamBar;

	private DXLabel emptyLbl;
	private DXLine div1;
	private DXLine div2;

	// Team 1/2
	private DashboardLayout layout1;
	private DashboardLayout layout2;

	// Which one currently showing?
	private DashboardLayout activeLayout;
	private bool updating;

	// Configuration
	private DashboardConfig config;

	// Eligible for force resync?
	private bool hasSync;

	/* Methods */

	// Post-construction initialization
	public void Init( DashboardConfig dashboardConfig )
	{
		config = dashboardConfig;

		updating = true;

		BackgroundColor = DXColors.Dark1;
		RowSpacing = 0;

		Horizontal = LayoutOptions.Fill;
		Vertical = LayoutOptions.Fill;

		IgnoreSafeArea = true;
		
		// Divider
		div1 = new DXLine
		{
			Thickness = 1,
			Color = DXColors.Dark1
		};

		// Team 1/2
		teamBar = new DashboardTeam
		{
			Config = config,
			TeamChanged = OnTeamChanged
		};

		// Divider
		div2 = new DXLine
		{
			Thickness = 1,
			Color = DXColors.Dark1
		};

		// Empty
		emptyLbl = new DXLabel
		{
			IsVisible = false,
			Resource = "dashboard.empty",

			TextColor = DXColors.Light1,
			Font = DXFonts.Roboto,
			FontSize = 30,

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

		// Create team segments
		teamBar.Init( config );

		updating = false;
	}

	// Sets currently active dashboard based on team selection
	private async Task SetActiveLayout( bool team1, bool update = false )
	{
		int index = team1 ? 0 : 1;

		if ( !updating )
		{
			updating = true;

			bool isLayout1 = (index == 0);

			// Team 1
			if ( isLayout1 )
			{
				Organization org = config.Organization;

				// Lazily create
				layout1 ??= new DashboardLayout()
				{
					CardTapped = OnCardTapped
				};

				layout1.Config = config;

				// Update card info
				layout1.CustomConfig = new CustomConfig
				{
					IsTeam1 = true,
					Color = org.Color,
					Name = org.Name
				};

				// Must re-create cards based on scope
				layout1.Init( config.Scope );
				
				activeLayout = layout1;
			}
			// Team 2
			else
			{
				// Lazily create
				layout2 ??= new DashboardLayout()
				{
					CardTapped = OnCardTapped
				};

				layout2.Config = config;

				// Update card info
				layout2.CustomConfig = new CustomConfig
				{
					IsTeam1 = false,
					Name = DXString.Get( "opponent.singular" ),
					Color = (config.Team2 == null) ? Opponent.DefaultColor : config.Team2.Color
				};

				// Must re-create cards based on scope
				layout2.Init( config.Scope );

				activeLayout = layout2;
			}

			// Refresh
			await UpdateData();

			// Show/hide each team
			if ( layout1 != null )
			{
				layout1.IsVisible = isLayout1;
			}
			if ( layout2 != null )
			{
				layout2.IsVisible = !isLayout1;
			}

			// Only redraw if necessary
			if ( update )
			{
				UpdateLayout();
			}

			updating = false;
		}
	}

	// Re-initializes specified layout to update custom card metrics
	public void UpdateActiveLayout( bool team1 )
	{
		string scope = config.Scope;

		// Primary
		if ( team1 )
		{
			layout1.Init( scope );
		}
		// Opponent
		else
		{
			layout2.Init( scope );
		}
	}

	// Refreshes data display with metrics for all dashboard cards
	private async Task UpdateData()
	{
		// Calculates and caches metric totals for all data sets
		await DashboardCache.Instance.CacheMetrics( config, teamBar.IsTeam1 );

		// Update display with new data
		activeLayout?.UpdateData();
	}

	// Shows fully populated dashboard form
	public async Task Show( bool sync )
	{
		hasSync = sync;

		IsVisible = true;

		// Make sure Sync/Edit buttons reset
		Reset();
		
		await SetActiveLayout( teamBar.IsTeam1 );
	}

	// Fully hides form
	public void Hide()
	{
		ToolBar toolbar = Shell.Instance.ToolBar;

		// Remove sync
		toolbar.RemoveCustom( 2 );
		toolbar.Custom2Tapped = null;

		IsVisible = false;
	}

	// Resets all dashboard card tap states
	public void Reset()
	{
		ToolBar toolbar = Shell.Instance.ToolBar;

		// Add back sync
		if ( hasSync )
		{
			AddSync();
		}
		// Remove export
		else
		{
			toolbar.RemoveCustom( 1 );
			toolbar.Custom1Tapped = null;
		}

		activeLayout?.Reset();
	}

	// Used to disable opponent when not applicable
	public void DisableTeam( bool team1, bool disabled )
	{
		teamBar.Disable( team1, disabled );
	}

	// Adds sync button to app toolbar
	private void AddSync()
	{
		ToolBar toolbar = Shell.Instance.ToolBar;

		toolbar.AddCustom( 1, "sync", "analyze.sync" );
		toolbar.Custom1Tapped = OnSyncTapped;
	}

	/* Event Callbacks */

	// Switches dashboards when team selected
	private async void OnTeamChanged( bool isTeam1 )
	{
		await SetActiveLayout( isTeam1, true );
		
		DXSpinner.Stop();
	}

	// Dashboard card was tapped
	private async void OnCardTapped( JsonCategory category )
	{
		DXSpinner.Start();

		string scopeName = config.ScopeName;

		// Cached JSON config
		JsonDashboard dashboard = DashboardCache.Instance.Dashboards[ category.Key ];

		// Build configuration for all reports on dashboard
		ReportConfig reportConfig = new()
		{
			Title = category.Title,
		
			Scope = config.Scope,
			ScopeName = scopeName,
			ScopeObject = config.ScopeObject,
		
			Organization = config.Organization,
			IsTeam1 = teamBar.IsTeam1,
		
			Team1 = config.Team1,
			Team2 = config.Team2,
		
			HasSync = hasSync,
			Dashboard = dashboard
		};
		
		Shell shell = Shell.Instance;
		
		// Init
		await shell.ReportForm.Init( reportConfig );
		
		// Show reports form for selected category
		shell.ShowReportForm( scopeName, category.Title );
	}

	// User forced resync of in-progress set/match
	private async void OnSyncTapped()
	{
		DXSpinner.Start();

		config.IsForceEligible = true;

		// Force sync
		await UpdateData();

		Shell.Instance.ToolBar.ResetCustom();
	}

	/* Layout */

	// Device/orientation specific layout
	public override void UpdateLayout( LayoutType type )
	{
		// Prevent redundant updates
		if ( activeLayout != null )
		{
			// Re-layout
			Layout();

			// Update children
			activeLayout.UpdateLayout( type );
			activeLayout.IsVisible = true;
		}
	}

	// MUST re-layout on every init and rotation
	private void Layout()
	{
		ClearAll();

		// Divider
		AddFixedRow( 1 );
		Add( div1, 0, 0 );

		// Team bar
		AddFixedRow( 56 );
		Add( teamBar, 0, 1 );

		// Divider
		AddFixedRow( 1 );
		Add( div2, 0, 2 );

		// Content
		AddStarRow();

		Add( emptyLbl, 0, 3 );

		if ( activeLayout != null )
		{
			Add( activeLayout, 0, 3 );
		}
	}
}

//
