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

using DXLib.UI.Control.Checkbox;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Provides utility methods for working with an analyze By Modifier (contact type) key. Note that the KeyModifier object
 * is the actual key.
 */
public class KeyModifier
{
	/* Properties */
	public string UniqueId { get; }
	public string ObjectName { get; }

	/* Methods */
	public KeyModifier( Stat stat )
	{
		// 'attack3.tip'
		UniqueId = GetKey( stat );
		
		// Read display name from LUT
		ObjectName = GetLabel( stat );
	}

	// Tests for equality between two modifier objects
	public override bool Equals( object obj )
	{
		return (obj is KeyModifier modifier) && modifier.UniqueId.Equals( UniqueId );
	}

	// Generates unique hash code for lists
	public override int GetHashCode()
	{
		return UniqueId.GetHashCode();
	}

	// Returns unique key for dimension analysis
	public static string GetKey( Stat stat )
	{
		string key = RecordHistory.GetModifierKey( stat );
		string modifier = stat.Modifier;
	
		// 'attack3.tip'
		return $"{key}.{modifier}";
	}

	// Creates display label for specified modifier ('Tip','Float')
	public static string GetLabel( Stat stat )
	{
		string modKey = RecordHistory.GetModifierKey( stat );
		string baseKey = $"modifier.{modKey}";
	
		// Read from LUT
		return (stat.Modifier == null) ? null : DXString.GetLookupValue( baseKey, stat.Modifier );
	}

	// Returns list of filter objects for this dimension
	public static List<object> GetFilter( List<object> objects )
	{
		return objects;
	}

	// Determines if modifier from specified stat passes given filter
	public static bool Filter( DataConfig config, List<object> filter, Stat stat )
	{
		// Only include relevant modifiers
		if ( Include( config.Key, stat ) )
		{
			// Check if modifier in filter list
			return ((filter == null) || filter.Contains( new KeyModifier( stat ) ));
		}
	
		return false;
	}

	// Determines if specified stat modifier relevant for given report type
	private static bool Include( string key, Stat stat )
	{
		if ( stat.Modifier != null )
		{
			return key switch
			{
				// Blocking: All
				JsonDashboard.BlockingKey => (stat.Action == Stats.BlockKey),
				
				// Defense: All
				JsonDashboard.DefenseKey => (stat.Action == Stats.DefenseKey),
				
				// Hitting: Attacks or any action resulting in kill
				JsonDashboard.HittingKey => (stat.Selector == Stats.AttackKey) || (stat.Result == Stats.KillKey),
				
				// Passing: Any non-receive first ball
				JsonDashboard.PassingKey => stat.Action switch
				{
					Stats.FirstKey or Stats.FreeballKey or Stats.PutbackKey => true,
				
					_ => false,
				},
				
				// Receive: All
				JsonDashboard.ReceiveKey => (stat.Action == Stats.ReceiveKey),
				
				// Serving: All
				JsonDashboard.ServingKey => (stat.Action == Stats.ServeKey),
				
				// Setting: Sets or any action resulting in assist
				JsonDashboard.SettingKey => (stat.Selector == Stats.SetKey) || (stat.Result == Stats.AssistKey),
				
				_ => false
			};
		}

		return false;
	}

	// Returns comma-delimited list of selected filter values
    public static string GetValues( List<object> filter )
	{
		int count = filter.Count;
		string[] values = new string[count];

		// Build comma delimited list
		for ( int i = 0; i < count; i++ )
		{
			object obj = filter[i];

			values[i] = (obj as KeyModifier)?.ObjectName;
		}

		return string.Join( ", ", values );
	}

	// Loads filter tree for dimension
	public static void Load( DXCheckboxNode tree, List<object> filter )
	{
		tree.SetChildObjects( filter );
	}

	// Updates filter list for dimension
	public static List<object> Update( DataConfig config, DataStats stats )
	{
		List<KeyModifier> list = [];
	
		// Build list of each modifier present in data
		foreach ( Stat stat in stats )
		{
			// Only include modifiers relevant for report
			if ( Include( config.Key, stat ) )
			{ 
				KeyModifier modifier = new( stat );
	
				if ( !list.Contains( modifier ) )
				{
					list.Add( modifier );
				}
			}
		}
	
		// Alpha sort
		return list.OrderBy( km => km.ObjectName ).Cast<object>().ToList();
	}
}

//
