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

using DXLib.Utils;

namespace iStatVball3;

/*
 * 3x2 grid of cells representing zones 1-6 of a lineup, with zones 4,3,2 in the front row, and zones 5,6,1 in the back row.
 */
public class TeamCourt : DXGridLayout
{
	/* Constants */

	// Faded preview mode
	private const double PreviewOpacity = 0.3;

	/* Properties */

	// Court for anonymous team?
	private bool IsAnonymous => (cells == null);

	/* Fields */
	private readonly TeamOverlay parent;
	private readonly DXAbsoluteGestures layout;

	// Underlying views
	private List<TeamCell> cells;

	/* Methods */
	public TeamCourt( TeamOverlay parent, DXAbsoluteGestures layout )
	{
		this.parent = parent;
		this.layout = layout;

		IsVisible = false;
	}

	// Performs post-construction initialization
	public void Init()
	{
		// Layout
		BackgroundColor = DXColors.Dark1;

		// 6 cells
		cells = new List<TeamCell>( Lineup.BaseEntries );

		// Create each cell
		for ( int zone = 1; zone <= Lineup.BaseEntries; zone++ )
		{
			cells.Add( new TeamCell( parent, zone ) );
		}
	}

	// Visually selects specified cell
	public void Select( int zone )
	{
		cells[ zone - 1 ].IsSelected = true;
	}

	// Find zone number (1-6) of libero on court, 0 if NA
	public int FindLibero()
	{
		// Search each cell
		for ( int zone = 1; zone < Lineup.LiberoZone1; zone++ )
		{
			if ( cells[ zone - 1 ].IsLibero )
			{
				return zone;
			}
		}

		// Not on court
		return 0;
	}

	// Disables buttons for sub and swap modes
	private void DisableSubSwap()
	{
		bool swapMode = parent.IsSwap;

		if ( parent.IsSub || swapMode )
		{
			// All number/position editing disabled
			foreach ( TeamCell cell in cells )
			{
				cell.IsEditDisabled = true;

				// Cannot sub/swap libero
				if ( cell.IsLibero )
				{
					cell.IsDisabled = true;
				}
			}

			// Swap is backrow only
			if ( swapMode )
			{
				cells[1].IsDisabled = true;
				cells[2].IsDisabled = true;
				cells[3].IsDisabled = true;
			}
		}
	}

	/* WHP */

	// Returns current server (zone 1)
	public LineupEntry GetServer()
	{
		return IsAnonymous ? null : cells[0].GetEntry();
	}

	// Returns current setter
	public LineupEntry GetSetter()
	{
		// Might be anonymous
		if ( !IsAnonymous )
		{
			List<LineupEntry> entries = GetTeam();

			// Search across backrow first
			for ( int i = 0; i < Lineup.BaseEntries; i++ )
			{
				int index = (4 + i) % Lineup.BaseEntries;
				LineupEntry entry = entries[ index ];

				if ( entry.IsSetter )
				{
					return entry;
				}
			}
		}

		// No setter
		return null;
	}

	// Returns list of all players currently on court (zones 1-6)
	public List<LineupEntry> GetTeam()
	{
		return GetEntries( 0 );
	}

	// Returns list of players currently in frontrow (zones 2-4)
	public List<LineupEntry> GetFrontrow()
	{
		List<LineupEntry> team = GetTeam();

		// Build frontrow list
		return [ team[1], team[2], team[3] ];
	}

	/* Get/Set */

	// Returns list of all players currently on court (rotation order)
	public List<Player> GetPlayers()
	{
		List<Player> list = new( Lineup.BaseEntries );

		// Ignore empty cells
		foreach ( TeamCell cell in cells )
		{
			if ( !cell.IsEmpty )
			{
				list.Add( cell.Player );
			}
		}

		return list;
	}

	// Returns individual lineup entry (rotation order)
	public LineupEntry GetEntry( int zone )
	{
		return cells[ zone - 1 ].GetEntry();
	}

	// Returns list of lineup entries for current court players (lineup order)
	public List<LineupEntry> GetEntries( int rotation )
	{
		// Rotation 0 returns list unmodified (rotation order)
		bool lineupOrder = (rotation > 0);

		List<LineupEntry> list = new( Lineup.BaseEntries );

		// Create each entry
		for ( int i = 0; i < Lineup.BaseEntries; i++ )
		{
			int index = lineupOrder ? Lineup.GetRotationIndex( i, rotation ) : i;

			TeamCell cell = cells[ index ];
			Player player = cell.Player;

			list.Add( new LineupEntry
			{
				Zone = (i + 1),

				Position = cell.Position,
				IsAltNumber = cell.IsAltNumber,

				PlayerId = player?.UniqueId,
				Player = player
			});
		}

		return list;
	}

	// Updates lineup display for specified entry
	public void SetEntry( LineupEntry entry, int zone )
	{
		cells[ zone - 1 ].SetEntry( entry );
	}

	// Updates lineup display with specified rotation offset
	public void SetEntries( List<LineupEntry> entries, int rotation )
	{
		bool blank = (entries.Count == 0);

		// Clear cell or copy from non-empty entry
		for ( int i = 0; i < Lineup.BaseEntries; i++ )
		{
			int index = Lineup.GetLineupIndex( i, rotation );

			cells[i].SetEntry( blank ? null : entries[ index ] );
		}
	}

	/* Show/Hide */

	// Shows court on specified side
	public void Show( bool sideA, Rect bounds, double teambarSize )
	{
		// Frontrow NA for libero swap
		DisableSubSwap();

		bool ios = DXDevice.IsIOS;
		bool wide = DXDevice.IsTabletWide;

		double statusHt = ios ? DXDevice.GetSafeTop() : 0;

		float scale = CourtView.DpScale;
		float size = (CourtView.CourtSize / scale);
		float net = (CourtView.NetSize / scale);

		float halfNet = (net / 2);

		double x = DXDevice.ExtraSafeArea().Left;
		double y = 0;

		// 2x3 arranged vertically for left/right sides
		if ( parent.IsLandscape )
		{
			// Account for teambar
			if ( wide )
			{
				x += teambarSize;
			}

			double middle = (bounds.Width / 2.0);

			x += sideA ? (middle - halfNet - size) : (middle + halfNet);
			y += bounds.Y + ((bounds.Height - size) / 2);
		}
		// 3x2 arranged horizontally for top/bottom sides
		else
		{
			// Account for teambar
			if ( wide )
			{
				y += teambarSize;
			}

			double middle = (bounds.Height / 2.0);

			x += (bounds.Width - size) / 2;
			y += statusHt + (sideA ? (middle - halfNet - size) : (middle + halfNet));
		}

		layout.SetBounds( this, x, y, size, size );

		IsVisible = true;
	}

	// Hides court
	public void Hide()
	{
		IsVisible = false;

		SetPreview( false );
	}

	// Turns translucent lineup preview mode on/off
	public void SetPreview( bool on )
	{
		Opacity = on ? PreviewOpacity : 1.0;

		// Forward to underlying cells
		foreach ( TeamCell cell in cells )
		{
			cell.IsPreview = on;
		}
	}

	/* Layout */

	// Redraws entire 3x2 court
	public override void UpdateLayout( LayoutType type )
	{
		ClearAll();

		base.UpdateLayout( type );

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

	// Landscape (4:3)
	protected override void Landscape()
	{
		bool tablet = DXDevice.IsTablet;

		Padding = tablet ? new Thickness( 0, 0, 4, 4 ) : new Thickness( 2, 2, 3, 3 );

		RowSpacing = tablet ? 0 : 2;
		ColumnSpacing = tablet ? 0 : 2;

		AddStarRows( 3 );
		AddStarColumns( 2 );

		// Left
		if ( parent.IsSideA )
		{
			// Backrow (5-6-1)
			Add( cells[4], 0, 0 );
			Add( cells[5], 0, 1 );
			Add( cells[0], 0, 2 );

			// Frontrow (4-3-2)
			Add( cells[3], 1, 0 );
			Add( cells[2], 1, 1 );
			Add( cells[1], 1, 2 );
		}
		// Right
		else
		{
			// Frontrow (2-3-4)
			Add( cells[1], 0, 0 );
			Add( cells[2], 0, 1 );
			Add( cells[3], 0, 2 );

			// Backrow (1-6-5)
			Add( cells[0], 1, 0 );
			Add( cells[5], 1, 1 );
			Add( cells[4], 1, 2 );
		}
	}

	// Portrait (3:4)
	protected override void Portrait()
	{
		bool tablet = DXDevice.IsTablet;

		Padding = tablet ? new Thickness( 0, 0, 4, 4 ) : new Thickness( 2, 2, 3, 3 );

		RowSpacing = tablet ? 0 : 2;
		ColumnSpacing = tablet ? 0 : 2;

		AddStarRows( 2 );
		AddStarColumns( 3 );

		// Top
		if ( parent.IsSideA )
		{
			// Backrow (1-6-5)
			Add( cells[0], 0, 0 );
			Add( cells[5], 1, 0 );
			Add( cells[4], 2, 0 );

			// Frontrow (2-3-4)
			Add( cells[1], 0, 1 );
			Add( cells[2], 1, 1 );
			Add( cells[3], 2, 1 );
		}
		// Bottom
		else
		{
			// Frontrow (4-3-2)
			Add( cells[3], 0, 0 );
			Add( cells[2], 1, 0 );
			Add( cells[1], 2, 0 );

			// Backrow (5-6-1)
			Add( cells[4], 0, 1 );
			Add( cells[5], 1, 1 );
			Add( cells[0], 2, 1 );
		}
	}

	// Widescreen Landscape (same as normal)
	protected override void WideLandscape()
	{
		Landscape();
	}

	// Widescreen Portrait (same as normal)
	protected override void WidePortrait()
	{
		Portrait();
	}

	// Mobile Landscape (same as tablet)
	protected override void MobileLandscape()
	{
		Landscape();
	}

	// Mobile Portrait (same as tablet)
	protected override void MobilePortrait()
	{
		Portrait();
	}
}

//
