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

namespace iStatVball3;

/*
 * Encapsulates all currently selected keys for each component of a log filter. Provides methods for filtering a stat
 * against the current configuration to determine if it should be included in the log display.
 */
public class Filter
{
	/* Properties */

	// Filter components
	public FilterDimension Teams { get; set; }
	public FilterDimension Rotations { get; set; }
	public FilterDimension Players { get; set; }

	public FilterDimension Actions { get; set; }
	public FilterDimension Selectors { get; set; }
	public FilterDimension Modifiers { get; set; }

	public FilterDimension Results { get; set; }
	public FilterDimension Errors { get; set; }
	public FilterDimension Faults { get; set; }

	public FilterDimension Ratings { get; set; }
	public FilterDimension StartAreas { get; set; }
	public FilterDimension EndAreas { get; set; }

	// External ref
	public Match Match { get; set; }

	/* Methods */

	// Filters specified stat list against all current filter lists
	public List<Stat> FilterStats( List<Stat> stats )
	{
		List<Stat> filtered = [];
		
		// Add to list if matches filter
		filtered.AddRange( stats.Where( FilterStat ) );

		return filtered;
	}

	// Filters specified individual stat against all filter components
	private bool FilterStat( Stat stat )
	{
		return FilterTeam( stat ) && FilterRotation( stat ) && FilterPlayer( stat ) &&
		       FilterAction( stat ) && FilterSelector( stat ) && FilterModifier( stat ) &&
		       FilterResult( stat ) && FilterError( stat ) && FilterFault( stat ) &&
		       FilterRating( stat ) && FilterStartArea( stat ) && FilterEndArea( stat );
	}

	// Determines if stat matches current Team filter
	private bool FilterTeam( Stat stat )
	{
		string statId = stat.IsPoint ? stat.Point.TeamId : stat.TeamId;
		string teamId = (statId == Match.Team1Id) ? statId : Match.Team2Id;

		// Point event includes team earning point (not causing)
		return Teams.Contains( teamId );
	}

	// Determines if stat matches current Rotation filter
	private bool FilterRotation( Stat stat )
	{
		int rotation = stat.Rotation;

		return Rotations.IsDisabled || (rotation == 0) || Rotations.Contains( rotation.ToString() );
	}

	// Determines if stat matches current Player filter
	private bool FilterPlayer( Stat stat )
	{
		// NA for opponent
		return (Players == null) || Players.AllSelected || (Players.Contains( stat.PlayerId ) && !stat.IsPoint);
	}

	// Determines if stat matches current Action filter
	private bool FilterAction( Stat stat )
	{
		return Actions.Contains( stat.Action );
	}

	// Determines if stat matches current Selector filter
	private bool FilterSelector( Stat stat )
	{
		// Not all actions have selectors
		bool hasSelector = stat.Action switch
		{
			Stats.SecondKey or Stats.ThirdKey or Stats.LineupKey or Stats.UpdateKey => true,
			
			_ => false
		};

		return (Selectors == null) || !hasSelector || Selectors.Contains( stat.Selector );
	}

	// Determines if stat matches current Modifier filter
	private bool FilterModifier( Stat stat )
	{
		bool hasModifier = !stat.IsOtherAction();

		return Modifiers.AllSelected || !hasModifier || Modifiers.Contains( stat.Modifier );
	}

	// Determines if stat matches current Result filter
	private bool FilterResult( Stat stat )
	{
		bool hasResult = !stat.IsOtherAction();

		return !hasResult || Results.Contains( stat.Result );
	}

	// Determines if stat matches current Error filter
	private bool FilterError( Stat stat )
	{
		return (Errors == null) || Errors.AllSelected || Errors.Contains( stat.Error );
	}

	// Determines if stat matches current Fault filter
	private bool FilterFault( Stat stat )
	{
		string fault = stat.Fault;

		return (Faults == null) || (fault == null) || Faults.Contains( fault );
	}

	// Determines if stat matches current Rating filter
	private bool FilterRating( Stat stat )
	{
		int? rating = stat.Rating;

		return (Ratings == null) || (rating == null) || Ratings.Contains( rating.ToString() );
	}

	// Determines if stat matches current Start Area filter
	private bool FilterStartArea( Stat stat )
	{
		bool hasStart = !stat.IsOtherAction();
		int startArea = stat.StartZone;

		return !hasStart || (startArea == 0) || StartAreas.Contains( startArea.ToString() );
	}

	// Determines if stat matches current End Area filter
	private bool FilterEndArea( Stat stat )
	{
		bool hasEnd = !stat.IsOtherAction();
		int endArea = stat.EndZone;

		return !hasEnd || (endArea == 0) || EndAreas.Contains( stat.EndZone.ToString() );
	}
}

//
