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

/*
 * Encapsulates all data necessary to populate the Box Score report. Box Score data is ONLY applicable for Match scope.
 */
public class MetricsBoxScore : DataMetrics
{
	/* Constants */
	private const int MaxSets = Match.MaxSets;
	private const string NA = Grid.NA;

	/* Properties */
	public string Team1 { get; set; }
	public string Team2 { get; set; }

	public string Site { get; set; }
	public string Date { get; set; }
	public string Attendance { get; set; }

	public string SeasonRecord { get; set; }
	public string Duration { get; set; }

	public string Referee1 { get; set; }
	public string Referee2 { get; set; }

	// Set scores (1-5)
	public int[] Scores1 { get; set; }
	public int[] Scores2 { get; set; }

	// Attack stats for each set (1-5)
	public int[] Attack_TotalKills { get; set; }
	public int[] Attack_TotalErrors { get; set; }
	public int[] Attack_TotalAttempts { get; set; }

	public float[] Attack_Efficiency { get; set; }

	// Block stats
	public float Block_TotalBlocks { get; set; }

	/* Fields */
	private int setCount;

	/* Methods */
	public MetricsBoxScore( bool total = false ) : base( total )
	{
		Scores1 = new int[ MaxSets ];
		Scores2 = new int[ MaxSets ];

		Attack_TotalKills = new int[ MaxSets ];
		Attack_TotalErrors = new int[ MaxSets ];
		Attack_TotalAttempts = new int[ MaxSets ];

		Attack_Efficiency = new float[ MaxSets ];

		// Must init values to NA
		for ( int i = 0; i < MaxSets; i++ )
		{
			Scores1[i] = IntNA;
			Scores2[i] = IntNA;

			Attack_TotalKills[i] = IntNA;
			Attack_TotalErrors[i] = IntNA;
			Attack_TotalAttempts[i] = IntNA;

			Attack_Efficiency[i] = FloatNA;
		}
	}

	// Loads all static data for Box Score report
	public static async Task<MetricsBoxScore> LoadData( DataConfig config )
	{
		MetricsBoxScore metrics = new();

		// Calc static match values
		Match match = (Match)config.ScopeObject;
		metrics.Accumulate( match );

		// Accumulate totals from each set
		foreach ( Set set in match.Sets )
		{
			DataConfig setConfig = new()
			{
				Scope = DataConfig.SetScope,
				ScopeObject = set,

				Organization = config.Organization,
				IsTeam1 = config.IsTeam1,

				Team1 = config.Team1,
				Team2 = config.Team2,

				Totals = new MetricsSkill( true )
			};

			DataStats stats = await DataFilter.Filter( setConfig );
			MetricsSkill totals = (MetricsSkill) setConfig.Totals;

			// Accumulate all variables
			foreach ( Stat stat in stats )
			{
				MetricsSkillAccumulator.Accumulate( totals, stat );

				// Up to 3 block assists per stat
				if ( stat.Result == Stats.BlockAssistsKey )
				{
					MetricsSkillAccumulator.Accumulate( totals, stat, 2 );
					MetricsSkillAccumulator.Accumulate( totals, stat, 3 );
				}
			}

			// Calculate statistics
			MetricsSkillCalculator.Calculate( totals );

			// Accumulate set totals
			metrics.AccumulateSet( totals );
		}

		return metrics;
	}

	// Accumulates static Box Score data (constant for match)
	public void Accumulate( Match match )
	{
		Team1 = match.Team1Name;
		Team2 = match.Team2Name;

		Site = (match.Venue == null) ? NA : match.Venue.Name;
		Date = (match.StartTime == null) ? NA : DXUtils.MonthFromDate( (DateTimeOffset)match.StartTime );
		Attendance = (match.Attendance == null) ? NA : $"{match.Attendance:n0}";

		// Won-Lost-Tied
		Season season = match.Season;
		SeasonRecord = (season.GetCompletedCount() == 0) ? NA : season.GetRecord();

		// Xhrs Ymin
		TimeSpan duration = match.GetDuration();
		Duration = (duration == TimeSpan.Zero) ? NA : DXUtils.FromDuration( match.GetDuration() );

		Referee1 = match.Referee1 ?? NA;
		Referee2 = match.Referee2 ?? NA;

		IList<Set> sets = match.Sets;

		// Scores for all sets (1-5)
		for ( int i = 0; i < sets.Count; i++ )
		{
			Scores1[i] = sets[i].Points1;
			Scores2[i] = sets[i].Points2;
		}
	}

	// Accumulates set-specific Box Score data (1-5 sets)
	public void AccumulateSet( MetricsSkill totals )
	{
		int i = setCount;

		// Attack stats one entry per set
		Attack_TotalKills[i] = totals.Attack_TotalKills;
		Attack_TotalErrors[i] = totals.Attack_TotalErrors;
		Attack_TotalAttempts[i] = totals.Attack_TotalAttempts;

		Attack_Efficiency[i] = totals.Attack_Efficiency;

		setCount++;

		// Block stats additive
		Block_TotalBlocks += totals.Block_TotalBlocks;
	}

	// Unused
	public override void Accumulate( DataConfig config, Stat stat, int number = 1 )
	{}

	// Unused
	public override void Calculate()
	{}
}

//
