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

using DXLib.UI;
using DXLib.UI.Layout;
using DXLib.UI.Container;

using DXLib.UI.Form;
using DXLib.UI.Form.Control;

using DXLib.Utils;

namespace iStatVball3;

/*
 * Implements the master view for raw tally stats, either being entered from paper, or edited in existing set stats.
 * There is a cell with editing controls for each stat category.
 */
public class EditTallyView : DXScroll
{
	/* Events */
	public Action PlayedChanged { get; set; }
	public Action TallyChanged { get; set; }

	/* Properties */
	public bool IsEditMode { get; set; }
	public bool IsDisabled { set => SetDisabled( value ); }

	/* Fields */
	private readonly DXVerticalLayout layout;
	private readonly DXCheckboxField playedField;

	// Underlying cells
	private readonly List<EditTallyCell> cells;

	// External ref
	private Set tallySet;

	/* Methods */
	public EditTallyView()
	{
		bool tablet = DXDevice.IsTablet;

		BackgroundColor = DXColors.Light4;
		Orientation = ScrollOrientation.Vertical;

		// Layout
		layout = new DXVerticalLayout
		{
			Padding = 0,
			Spacing = 10,
			
			Horizontal = LayoutOptions.Fill,
			Vertical = LayoutOptions.Fill,
			
			IgnoreSafeArea = true
		};

		// Played in set?
		playedField = new DXCheckboxField
		{
			WidthRequest = tablet ? 200 : 150,
			Horizontal = LayoutOptions.Start,

			IsDisabled = true,

			Key = "played",
			Text = "tally.played",
			Checked = false,
			Hint = DXFormControl.HintType.None,
			Help = null,

			CheckboxToggled = OnPlayedToggled
		};

		playedField.Init();
		playedField.SetState( DXFormControl.ControlState.Normal );

		layout.Add( playedField );

		Content = layout;

		// Allocate container
		cells = [];
	}

	// Post construction initialization
	public void Init( Set set )
	{
		tallySet = set;

		// Tally editing uses Legacy categories
		var categories = DXString.GetLookupTable( "legacy" );

		// Create each category cell
		foreach ( string key in categories.Keys )
		{
			EditTallyCell cell = new()
			{
				IsEditMode = IsEditMode,
				TallyChanged = TallyChanged
			};

			// Initialize
			cell.Init( key, categories[ key ] );
			cells.Add( cell );

			// Cell row
			layout.Add( cell );
		}
	}

	// Determines if any cell in view has been edited
	public bool HasChanges()
	{
		// Check each cell, also include 'Played in set' field
		return cells.Any( cell => cell.HasChanges ) || playedField.HasChanges;
	}

	// Determines if any tally control currently has non-zero value
	private bool HasValue()
	{
		return cells.Any( cell => cell.HasValue() );
	}

	// Populates view with tally data for specified player
	public void SetPlayer( Player player, IDictionary<string,int> summary, MetricsSkill metrics )
	{
		IsDisabled = false;

		// Populate each cell
		foreach ( EditTallyCell cell in cells )
		{
			cell.Populate( summary, metrics );
		}

		// Set considered played if any stat entered
		UpdatePlayed( player, summary, metrics );
	}

	// Updates tally stats in summary cache for specified player
	public void UpdateStats( Player player, StatSummary summary, MetricsSkill metrics )
	{
		var summaryList = summary.PlayerStats;
		string key = player.RootId;

		// Create if does not yet exist
		if ( !summaryList.TryGetValue( key, out Dictionary<string,int> value ) )
		{
            value = new Dictionary<string,int>();
            summaryList.Add( key, value );
		}

		var playerSummary = value;

		// Played in set? (MUST be first)
		UpdatePlayed( player, playerSummary, metrics );

		// Increment set count ONLY for paper matches 
		if ( tallySet.Match.IsPaper )
		{
			playerSummary[ StatSummary.PlayedKey ] = (playedField.Checked ? 1 : 0);
		}

		// Update stats from each cell
		foreach ( EditTallyCell cell in cells )
		{
			cell.UpdateStats( playerSummary, metrics );
		}
	}

	// Updates checked/disabled states for 'played in set' field
	private void UpdatePlayed( Player player, IDictionary<string,int> summary, MetricsSkill metrics )
	{
		if ( player != null )
		{
			bool played = false;

			// Check if marked played in raw summary stats
			if ( summary != null )
			{
				const string playedKey = StatSummary.PlayedKey;

				// Marked as played
				played = summary.ContainsKey( playedKey ) && (summary[ playedKey ] > 0);
			}

			// Check if marked played in metrics
			if ( metrics != null )
			{
				played = played || (metrics.SetsPlayed > 0);
			}

			bool hasTally = HasValue();

			// Checked if already checked or has any tally value
			playedField.Checked = playedField.Checked || (played || hasTally);

			// Disabled once any tally value entered
			playedField.IsDisabled = hasTally;
		}
	}

	// Disables all controls in the view
	private void SetDisabled( bool disabled )
	{
		playedField.IsDisabled = disabled;

		foreach ( EditTallyCell cell in cells )
		{
			cell.IsDisabled = disabled;
		}
	}

	/* Event Callbacks */

	// User toggled 'Played in set', notify listener
	private void OnPlayedToggled()
	{
		PlayedChanged?.Invoke();
	}

	/* Layout */

	// Redraws entire tally view
	public override void UpdateLayout( LayoutType type )
	{
		base.UpdateLayout( type );

		bool ios = DXDevice.IsIOS;

		layout.Padding = new Thickness( (ios ? 20 : 15), 15 );

		// Update children
		foreach ( EditTallyCell cell in cells )
		{
			cell.UpdateLayout( type );
		}
	}
}

//
