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

namespace iStatVball3;

/*
 * Encapsulates the edit log header, roster, and flyouts so that they can be embedded in either the set edit form or the
 * log drawer during recording.
 */
public class EditLogView : DXGridLayout
{
	/* Properties */

	// Currently selected roster player(s)
	public Player Player => roster.GetSelectedPlayer();
	public List<Player> Players => roster.GetSelectedPlayers();

	// Current flyout selections
	public int? Rating => flyouts.Rating;
	public string Modifier => flyouts.Modifier;
	public string Selector => GetSelector();

	public string Fault => flyouts.Fault;

	/* Fields */
	private readonly LineupMenuView roster;

	private readonly EditLogHeader header;
	private readonly EditLogFlyouts flyouts;

	private readonly EditLogController controller;

	// External ref
	private Set editSet;

	// Stat being edited
	private Stat currentStat;

	/* Methods */
	public EditLogView( EditLogController controller )
	{
		this.controller = controller;

		// Layout
		Padding = 0;
		RowSpacing = 0;
		ColumnSpacing = 0;

		Horizontal = LayoutOptions.Fill;
		Vertical = LayoutOptions.Fill;

		IgnoreSafeArea = true;

		// Roster
		roster = new LineupMenuView
		{
			IsVisible = false,
			Embedded = true,

			Mode = LineupMenuView.SelectMode.Single,
			BackgroundColor = DXColors.Light1,

			HasTallRows = true,
			HasModified = false,

			PlayerSelected = OnPlayerSelected
		};

		// Header
		header = [];

		// Flyouts
		flyouts = new EditLogFlyouts
		{
			Selected = OnFlyoutSelected,
			FaultSelected = OnFaultSelected
		};
	}

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

		Match match = set.Match;

		// Init header
		header.Init( set );

		List<Player> players = match.Season.GetPlayers();

		// Populate roster
		roster.Init( players.Count, false, false );
		roster.SetPlayers( players );

		// MUST be last
		roster.Color = match.Team1Color;
	}

	/* Get */

	// Returns current flyout selector
	private string GetSelector()
	{
		string selector = flyouts.Selector;

		// MUST account for empty 2nd ball selector
		return ((selector == null) && (currentStat.Action == Stats.SecondKey)) ? Stats.SetKey  : selector;
	}

	/* Set */

	// Populates components with specified stat
	public void SetStat( Stat stat )
	{
		currentStat = stat;

		// Populate header
		header.SetStat( stat );

		// Roster only visible for primary team action events
		bool hasRoster = (stat.TeamId == editSet.Match.Team1.UniqueId) && stat.IsAction;

		// Select player
		if ( hasRoster )
		{
			roster.Select( stat );
		}

		roster.IsVisible = hasRoster;

		// Show flyouts
		flyouts.SetStat( stat );
		flyouts.Show( stat.IsFault );
	}

	// Updates modifier flyouts
	public void SetModifiers( Stat stat, bool multiBlock )
	{
		flyouts.SetModifiers( stat, multiBlock );
		flyouts.Show( stat is { IsFault: true } );
	}

	// Clears all data display
	public void ClearStat()
	{
		currentStat = null;

		header.ClearStat();
		flyouts.Hide();

		roster.IsVisible = false;
	}

	/* Update */

	// Updates block solo/assist based on number of players
	public static void UpdateBlockResult( Stat stat )
	{
		if ( stat.Result is Stats.BlockKey or Stats.BlockAssistsKey )
		{
			stat.Result = stat.IsMultiBlock ? Stats.BlockAssistsKey : Stats.BlockKey;
		}
	}

	// Updates stat following specified stat based on changed selector
	public static void UpdateNextEvent( LogEvent evt, LogEvent nextEvt )
	{
		Stat stat = evt.Stat;

		if ( !stat.IsError )
		{
			Stat nextStat = nextEvt.Stat;

			switch ( stat.Selector )
			{
				// Contact following 2nd Ball Set over is 1st Ball
				case Stats.SetKey:
				{
					nextStat.Action = Stats.FirstKey;
					break;
				}
				// Contact following 2nd/3rd Ball Attack is Defense
				case Stats.AttackKey:
				{
					nextStat.Action = Stats.DefenseKey;

					// Result changes to Dig
					if ( !nextStat.IsError )
					{
						nextStat.Result = Stats.DigKey;
					}

					break;
				}
				// Contact following 3rd Ball Free is Freeball
				case Stats.FreeKey:
				{
					nextStat.Action = Stats.FreeballKey;

					// Result changes to Attempt
					if ( !nextStat.IsError )
					{
						nextStat.Result = Stats.AttemptKey;
					}

					break;
				}
			}
		}
	}

	/* Event Callbacks */

	// User selected player, update parent controller
	private void OnPlayerSelected( Player player, bool cancel )
	{
		controller.OnPlayerSelected( player );
	}

	// User selected rating/modifier/selector from flyout menu
	private void OnFlyoutSelected( FlyoutBar.FlyoutType type, int index )
	{
		controller.OnFlyoutSelected( type, index );
	}

	// User selected fault from fault flyout
	private void OnFaultSelected()
	{
		controller.OnFaultSelected();
	}

	/* Layout */

	// Redraws entire view and child components
	public override void UpdateLayout( LayoutType type )
	{
		ClearAll();

		base.UpdateLayout( type );
	}

	// Landscape (4:3)
	protected override void Landscape()
	{
		LayoutTablet();
	}

	// Portrait (3:4)
	protected override void Portrait()
	{
		LayoutTablet();
	}

	// Mobile Landscape
	protected override void MobileLandscape()
	{
		LayoutMobile();
	}

	// Mobile Portrait
	protected override void MobilePortrait()
	{
		LayoutMobile();
	}

	// Updates all tablet layouts
	private void LayoutTablet()
	{
		// 2 rows
		AddFixedRow( 60 );      // 0: header
		AddStarRow();           // 1: roster, flyouts

		// 2 columns
		AddStarColumn( 50 );    // 0: roster
		AddStarColumn( 50 );    // 1: flyouts

		// Roster background
		Fill( DXColors.Light1, 0, 1 );

		// Add components
		Add( header, 0, 0, 2, 1 );
		Add( roster, 0, 1 );
		Add( flyouts, 1, 1 );
	}

	// Updates all mobile layouts
	private void LayoutMobile()
	{
		// 2 rows
		AddFixedRow( 44 );      // 0: header
		AddStarRow();           // 1: roster, flyouts

		// 2 columns
		AddStarColumn( 48 );    // 0: roster
		AddStarColumn( 52 );    // 1: flyouts

		// Roster background
		Fill( DXColors.Light1, 0, 1 );

		// Add components
		Add( header, 0, 0, 2, 1 );
		Add( roster, 0, 1 );
		Add( flyouts, 1, 1 );
	}
}

//
