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

using System.Collections.ObjectModel;

using Syncfusion.Maui.TreeView;
using Syncfusion.TreeView.Engine;

using DXLib.UI;

namespace iStatVball3;

/*
 * An SfTreeView used to display a hierarchical tree of Teams, Seasons, and Players for selecting a Root link.
 */
public class RootTree : SfTreeView
{
	/* Events */
	public Action Populated { get; set; }
	public Action<RootTreeData> Selected { get; set; }

	/* Methods */
	public RootTree()
	{
		// Populate on demand
		NotificationSubscriptionMode = TreeViewNotificationSubscriptionMode.PropertyChange;
		NodePopulationMode = TreeNodePopulationMode.OnDemand;

		// Manual expand, animated
		ExpanderPosition = TreeViewExpanderPosition.Start;
		ExpandActionTarget = TreeViewExpandActionTarget.Node;
		AutoExpandMode = TreeViewAutoExpandMode.None;
		IsAnimationEnabled = true;

		// Single select
		SelectionMode = TreeViewSelectionMode.Single;
		SelectionBackground = DXColors.Accent1;

		// Custom sizing
		ExpanderWidth = 20;
		Indentation = 10;

		ChildPropertyName = "SubData";

		// Custom data
		ItemTemplateContextType = ItemTemplateContextType.Node;
		ItemTemplate = new RootTreeSelector();

		// Event handling
		Loaded += OnLoaded;
		SelectionChanged += OnSelectionChanged;
		QueryNodeSize += OnQueryNodeSize;
	}

	// Post-construction initialization, build tree
	public async Task<int> Init( Season currentSeason )
	{
		int totalSeasonCount = 0;

		Organization org = currentSeason.Team.Organization;
		ObservableCollection<RootTreeData> data = [];

		// Teams sorted alpha
		var teams = org.Teams.OrderBy( t => t.Name );

		// Populate root level
		foreach ( Team team in teams )
		{
			int seasonCount = 0;

			// Team node
			RootTreeData teamNode = new()
			{
				Tree = this,
				Name = team.Name,
				
				SubData = []
			};

			// Seasons sorted newest first
			var seasons = team.Seasons.OrderByDescending( s => s.StartDate );

			// Populate season level
			foreach ( Season season in seasons )
			{
				// Cannot link with player from same or future season
				if ( !season.Equals( currentSeason ) && (season.StartDate.CompareTo( currentSeason.EndDate ) <= 0) )
				{
					seasonCount++;
					totalSeasonCount++;

					// MUST make sure roster populated
					await season.PopulateRoster();

					// Season node
					RootTreeData seasonNode = new()
					{
						Tree = this,
						Name = season.Name,
						
						SubData = []
					};

					// Players sorted alpha
					var players = season.Players.OrderBy( p => p.LastName );

					// Populate leaf object level
					foreach ( Player player in players )
					{
						// Player node
						RootTreeData playerNode = new()
						{
							Tree = this,

							Season = season,
							Object = player,

							Name = player.FullName,
							Number = player.Number
						};

						seasonNode.SubData.Add( playerNode );
					}

					teamNode.SubData.Add( seasonNode );
				}
			}

			// Ignore team if no eligible seasons
			if ( seasonCount > 0 )
			{
				data.Add( teamNode );
			}
		}

		ItemsSource = data;

		// Allow caller to handle empty result set
		return totalSeasonCount;
	}

	/* Event Callbacks */

	// Tree has been fully populated, notify listener
	private void OnLoaded( object sender, TreeViewLoadedEventArgs args )
	{
		Populated?.Invoke();
	}

	// User selected player object
	private void OnSelectionChanged( object sender, ItemSelectionChangedEventArgs args )
	{
		if ( SelectedItem != null )
		{
			RootTreeData root = SelectedItem as RootTreeData;

			// Callback registered listener
			Selected?.Invoke( root );
		}
	}

	// Handles custom node sizing
	private static void OnQueryNodeSize( object sender, QueryNodeSizeEventArgs args )
	{
		// Height varies by node level
		args.Height = args.Node?.Level switch
		{
			0 => 40,
			1 => 30,
			2 => 35,
			
			_ => args.Height
		};

		args.Handled = true;
	}
}

//
