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

using DXLib.Data;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Encapsulates all variables and statistics for Sideout related metrics. Provides utility methods for variable
 * accumulation and statistic calculation.
 */
public class MetricsSideout : DataMetrics
{
	/* Properties */

	// Variables
	public int Attempts { get; set; }
	public int Sideouts { get; set; }

	public int FirstServes { get; set; }
	public int FirstBalls { get; set; }

	public int Transitions { get; set; }
	public int Touches { get; set; }
	public int Time { get; set; }

	// Statistics
	public float Percent { get; set; }

	public float FirstServePercent { get; set; }
	public float FirstBallPercent { get; set; }

	public float AveragePoints { get; set; }
	public float AverageTransitions { get; set; }
	public float AverageTouches { get; set; }

	public float AverageTime { get; set; }
	public string AverageTimeStr { get; set; }

	/* Methods */
	public MetricsSideout( bool total = false ) : base( total )
	{}

	// Accumulates all dimensional variables from specified stats list
	public static void AccumulateDimension( DataConfig config, DataStats stats )
	{
		config.Dimension = new DataDimension();
		config.Totals = new MetricsSideout( true );

		MetricsSideout totals = (MetricsSideout)config.Totals;

		// Single pass through stats list
		foreach ( Stat stat in stats )
		{
			// Only care about points where specified team receiving
			if ( stat.IsPoint && (stat.Point.ReceiveId == config.TeamId) )
			{
				// Create outer/inner keys for dimension
				string key = DataFilter.BuildDimension( config, stat, 1, new MetricsSideout() );

				// Accumulate all metrics for dimension value
				if ( key != null )
				{
					config.Dimension.Metrics[ key ].Accumulate( config, stat, 1 );
				}

				// Totals
				totals.Accumulate( config, stat );
			}
		}
	}

	// Accumulates all variables for specified stat
	public override void Accumulate( DataConfig config, Stat stat, int number = 1 )
	{
		// Only care about points
		if ( stat.IsPoint )
		{
			StatPoint point = stat.Point;
			
			// Where specified team receiving
			if ( (point != null) && (point.ReceiveId == config.TeamId) )
			{
				// Every opponent serve is sideout attempt
				Attempts++;

				// Successful sideout conversion
				if ( point.Sideout )
				{
					Sideouts++;

					// Track averages
					Transitions += point.Transitions;
					Touches += point.Touches;
					Time += point.Duration;

					// Sided-out on first serve of series
					if ( point.ServeCount == 1 )
					{
						FirstServes++;

						// Sided-out on first ball over
						if ( point.Transitions <= 2 )
						{
							FirstBalls++;
						}
					}
				}
			}
		}
	}

	// Calculates all statistics for pre-accumulated variables
	public override void Calculate()
	{
		float attempts = Attempts;
		float sideouts = Sideouts;

		bool hasAttempts = (attempts > 0);

		// Sideout %, FSSO %, FBSO %
		Percent = hasAttempts ? (sideouts / attempts) : FloatNA;
		FirstServePercent = hasAttempts ? (FirstServes / attempts) : FloatNA;
		FirstBallPercent = hasAttempts ? (FirstBalls / attempts) : FloatNA;

		bool hasSideouts = (sideouts > 0);

		// Averages
		AveragePoints = hasSideouts ? (attempts / sideouts) : FloatNA;
		AverageTransitions = hasSideouts ? (Transitions / sideouts) : FloatNA;
		AverageTouches = hasSideouts ? (Touches / sideouts) : FloatNA;
		AverageTime = hasSideouts ? (Time / sideouts) : FloatNA;

		AverageTimeStr = hasSideouts ? DXUtils.FromDuration( (int)AverageTime, true ) : DXData.NaN;
	}
}

//
