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

namespace iStatVball3;

/*
 * Accumulates all scoring related metrics for the Player dimension.
 */
public static class MetricsScoringPlayer
{
	/* Methods */

	// Accumulates all dimensional variables from specified stats list
	public static void AccumulateDimension( DataConfig config, DataStats stats )
	{
		// Accumulate list of all players in scope
		List<Player> players = DataFilter.GetPlayers( config );

		// Create row for each player
		foreach ( Player player in players )
		{
			BuildDimension( config, player );
		}

		// Stats list already filtered for scoring
		foreach ( Stat stat in stats )
		{
			Accumulate( config, players, stat );
		}
	}

	// Accumulates all scoring metrics for specified stat
	private static void Accumulate( DataConfig config, List<Player> players, Stat stat )
	{
		// Earned points/unforced errors come from action
		if ( stat.IsAction )
		{
			AccumulatePointsErrors( config, players, stat );
		}
		// +/- comes from point
		else if ( stat.IsPoint )
		{
			AccumulatePlusMinus( config, players, stat.Point );
		}
	}

	// Accumulates all earned point and unforced error metrics
	private static void AccumulatePointsErrors( DataConfig config, List<Player> players, Stat stat )
	{
		bool earned = stat.IsEarned();
		bool error = stat.IsError;

		bool earnable = stat.IsEarnable();
		bool errorable = stat.IsErrorable();

		if ( stat.Player != null )
		{
			if ( config.GetMetrics( stat.Player ) is MetricsScoring metrics )
			{
				// Earned point attempt
				if ( earnable )
				{
					metrics.PointAttempts += 1;
				}

				// Unforced error attempt
				if ( errorable )
				{
					metrics.ErrorAttempts += 1;
				}

				// Earned point
				if ( earned )
				{
					metrics.Points += 1;
				}
				// Unforced error
				else if ( error )
				{
					metrics.Errors += 1;
				}
			}
		}

		if ( config.Totals is MetricsScoring totals )
		{
			// Team totals can include anonymous stats
			if ( earnable )
			{
				totals.PointAttempts += 1;
			}

			if ( errorable )
			{
				totals.ErrorAttempts += 1;
			}

			if ( earned )
			{
				totals.Points += 1;
				totals.PointsTeam += 1;
			}
			else if ( error )
			{
				totals.Errors += 1;
				totals.ErrorsTeam += 1;
			}
		}

		// Track team totals used for player line items
		foreach ( Player player in players )
		{
			if ( config.GetMetrics( player ) is MetricsScoring metrics )
			{
				if ( earned )
				{
					metrics.PointsTeam += 1;
				}
				else if ( error )
				{
					metrics.ErrorsTeam += 1;
				}
			}
		}
	}

	// Accumulates all +/- scoring metrics
	private static void AccumulatePlusMinus( DataConfig config, List<Player> players, StatPoint point )
	{
		// Point won by this team?
		bool pointWon = (point.TeamId == config.TeamId);

		// +/- only awarded to players on court at time of point
		for ( int rot = 0; rot < Lineup.BaseEntries; rot++ )
		{
			Player player = DataMetrics.GetPlayer( players, point.PlayerIds1[ rot ] );

			if ( player != null )
			{
				// Add to player dimension
				if ( config.GetMetrics( player ) is MetricsScoring metrics )
				{
					if ( pointWon )
					{
						metrics.Plus += 1;
					}
					else
					{
						metrics.Minus += 1;
					}

					metrics.Played += 1;
				}
			}
		}

		// Accumulate team totals
		if ( config.Totals is MetricsScoring totals )
		{
			if ( pointWon )
			{
				totals.Plus += 1;
			}
			else
			{
				totals.Minus += 1;
			}

			totals.Played += 1;
		}
	}

	// Builds dimension (row) entry for specified player
	private static void BuildDimension( DataConfig config, Player player )
	{
		// Validate access control
		if ( config.HasAccess( player ) )
		{
			// Check for dimension filter
			if ( (config.OuterFilter == null) || config.OuterFilter.Contains( player ) )
			{
				// Keyed by root ID
				string key = player.RootId;
				string label = player.GetAnalyzeName( config.MaxLabelLen );

				var metricsList = config.Dimension.Metrics;

				// Prevent duplicates
				if ( !metricsList.ContainsKey( key ) )
				{
					// Create new dimension
					MetricsScoring metrics = new()
					{
						Type = KeyDimension.PlayerKey,
						TypeKey = null,
						TypeLabel = null,

						TypeObject = player,

						Key = key,
						Label = label
					};

					metricsList.Add( key, metrics );
				}
			}
		}
	}
}

//
