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

using DXLib.Utils;

namespace iStatVball3;

/*
 * Responsible for serialization of match stats and metadata into Bound JSON export format.
 */
public static class VBSerializer
{
	/* Constants */
	private const string Version = "1.0";

	/* Methods */

	// Serializes top-level metadata and entire match tree
	public static async Task<VBExport> Serialize( Match match )
	{
		// Create top-level object
		VBExport vbExport = new()
		{
			Version = Version,
			AppVersion = App.AppVersion,
			Date = DXUtils.TimestampFromDate( DXUtils.Now() ),
			
			// Serialize match data tree
			Match = await SerializeMatch( match )
		};

		return vbExport;
	}

	// Serializes match into object ready for serialization
	private static async Task<VBMatch> SerializeMatch( Match match )
	{
		// Metadata
		VBMatch vbMatch = new()
		{
			UniqueId = match.UniqueId,
			Date = DXUtils.TimestampFromDate( match.MatchTime ),

			Team1 = match.Team1Name,
			Team2 = match.Team2Name,

			Result = DXString.Get( match.GetResultRsrc() ),

			Sets1 = match.Sets1,
			Sets2 = match.Sets2,

			Scores1 = new List<int>(),
			Scores2 = new List<int>()
		};

		// Set scores
		foreach ( Set set in match.Sets )
		{
			vbMatch.Scores1.Add( set.Points1 );
			vbMatch.Scores2.Add( set.Points2 );
		}

		// Roster
		SerializeRoster( match, vbMatch );

		// Starting lineup
		await SerializeLineup( match, vbMatch );

		// Player stats
		await SerializeStats( match, vbMatch );

		return vbMatch;
	}

	// Adds full roster to specified export object
	private static void SerializeRoster( Match match, VBMatch vbMatch )
	{
		List<Player> roster = match.Season.Players;
		vbMatch.Roster = new List<VBPlayer>( roster.Count );

		// Add each player to roster
		foreach ( Player player in roster )
		{
			VBPlayer vbPlayer = new()
			{
				UniqueId = player.RootId,

				FirstName = player.FirstName,
				LastName = player.LastName,

				Number = player.Number,
				AltNumber = player.AltNumber,

				Positions = new List<string>( player.Positions.Count )
			};

			// Add positions
			foreach ( string position in player.Positions )
			{
				vbPlayer.Positions.Add( position );
			}

			vbMatch.Roster.Add( vbPlayer );
		}
	}

	// Adds starting lineup to specified export object
	private static async Task SerializeLineup( Match match, VBMatch vbMatch )
	{
		// Get list of players on court at first point of first set
		IList<string> lineup = await match.GetStartingLineup();

		if ( lineup != null )
		{
			vbMatch.Lineup = new List<string>( lineup.Count );

			// Add players to export
			foreach ( string playerId in lineup )
			{
				if ( playerId != null )
				{
					vbMatch.Lineup.Add( playerId );
				}
			}
		}
	}

	// Adds players stats for specified match to export object
	private static async Task SerializeStats( Match match, VBMatch vbMatch )
	{
		// Configure query
		DataConfig config = new()
		{
			Scope = "match",
			ScopeObject = match,

			Organization = match.Season.Organization,
			IsTeam1 = true,

			Team1 = match.Team1,
			Team2 = null,

			Action = null,
			OuterDim = "player",
			InnerDim = null,

			DataSet = "skills"
		};

		// Accumulate all match stats (metrics only)
		DataStats stats = await DataFilter.Filter( config );
		await DataDimension.ProcessDimension( config, stats );

		var metricsList = config.Dimension.Metrics.Values;

		vbMatch.Stats = new List<VBStats>( metricsList.Count );

		// Add stats for each player
		foreach ( DataMetrics metrics in metricsList )
		{
			if ( metrics.TypeObject is Player player )
			{
				// Calculate variables
				if ( metrics is MetricsSkill ms )
				{
					MetricsSkillCalculator.Calculate( ms );

					// Create export object
					VBStats vbStats = new()
					{
						PlayerId = player.RootId,

						SetsPlayed = ms.SetsPlayed,

						Kills = ms.Attack_TotalKills,
						KillErrors = ms.Attack_TotalErrors,
						KillAttempts = ms.Attack_TotalAttempts,

						Assists = ms.Set_TotalAssists,

						ServeSuccesses = (ms.Serve_Attempts - ms.Serve_Errors),
						ServeAttempts = ms.Serve_Attempts,
						ServeAces = ms.Serve_Aces,

						Digs = ms.Defense_Digs,

						BlockAssists = ms.Block_Assists,
						BlockSolos = ms.Block_Blocks
					};

					vbMatch.Stats.Add( vbStats );
				}
			}
		}
	}
}

//
