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

using DXLib.Utils;

namespace iStatVball3;

/*
 * Implements one cell in a 3x2 lineup grid. Each cell represents one zone (1-6) and includes panels for up to 2
 * substitutions/swaps.
 */
public class LineupReplaceCell : LineupPanelCell
{		
	/* Constants */
	private const string OneKey = "1";
	private const string TwoKey = "2";

	/* Fields */
	private DXLabel zoneLbl;
	private DXSegmentBar segmentBar;

	// Panels
	private readonly LineupReplacePanel panel1;
	private readonly LineupReplacePanel panel2;

	/* Methods */

	// NO UI in constructor
	public LineupReplaceCell( LineupReplace parent, int zone ) : base( zone )
	{
		// Panel 1
        panel1 = new LineupReplacePanel( parent, Zone )
        {
            Changed = OnChanged
        };

		// Panel 2
        panel2 = new LineupReplacePanel( parent, Zone )
        {
            Changed = OnChanged
        };
    }

    // Post construction initialization
    public override void Init( Color color, bool editable )
	{
		base.Init( color, editable );

		BackgroundColor = DXColors.Dark2;

		// Zone
		zoneLbl = new DXLabel
		{
			Text = Zone.ToString(),

			TextColor = DXColors.Dark1,
			Font = DXFonts.OswaldBold,

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};

		// Starters/Subs/Swaps
		segmentBar = new DXSegmentBar()
		{
			Mode = DXSegmentBar.SegmentMode.Text,

			FillColor = DXColors.Dark2,
			TextColor = DXColors.Light1,
			SelectColor = DXColors.Light1,

			// MUST be Fill
			Horizontal = LayoutOptions.Fill,
			Vertical = LayoutOptions.Center,

			Selected = OnSelected
		};

		segmentBar.Init();

		// Add segments
		segmentBar.AddSegment( OneKey, "replace.1" );
		segmentBar.AddSegment( TwoKey, "replace.2" );

		// Layout panel 1 only
		panel1.Init( Color );

		// Always start with panel 1
		segmentBar.SelectedKey = OneKey;
		
        IsInitialized = true;
	}

	/* Entries */

	// Returns replacement entries from panels 1 and 2 (DEEP COPY)
	public List<LineupEntryReplace> GetEntries()
	{
		List<LineupEntryReplace> entries = [];

		// Entry 1
		LineupEntryReplace entry1 = panel1.GetEntry();

		if ( entry1 != null )
		{
			entries.Add( entry1 );
		}

		// Entry 2
		LineupEntryReplace entry2 = panel2.GetEntry();

		if ( entry2 != null )
		{
			entries.Add( entry2 );
		}

		return entries;
	}

	// Populates a lineup entry for this cell
	public void SetEntry( LineupEntryReplace entry )
	{
		LineupReplacePanel panel = panel1.IsPopulated() ? panel2 : panel1;

		// If panel 1 full, use panel 2
		panel.SetEntry( entry );
	}

	// Returns list of 0-4 players currently in either panel of cell
	public List<Player> GetPlayers()
	{
		List<Player> players = [];

		// 1
		players.AddRange( panel1.GetPlayers() );

		// 2
		if ( panel2.IsInitialized )
		{
			players.AddRange( panel2.GetPlayers() );
		}

		return players;
	}

    /* Update */

	// Forces full redraw of cell
    public override void Update()
    {
		panel1.Update();

		// Only redraw Panel 2 if necessary
		if ( panel2.IsInitialized )
		{
			panel2.Update();
		}
    }

    /* Validation */

    // Determines if either panel contains specified OUT/IN player
    public bool HasPlayer( Player player, LineupReplaceRow.RowType type )
	{
		return panel1.HasPlayer( player, type ) || (panel2.IsInitialized && panel2.HasPlayer( player, type ));
	}

	// Only valid if panels empty or populated without duplicates
	public bool IsValid()
	{
		List<Player> players = GetPlayers();

		// Check for duplicate across panels
		foreach ( Player player in players )
		{
			Player dup = FindDuplicate( player );

			if ( dup != null )
			{
				return false;
			}
		}

		// Check for populated and no duplicate within panel
		return panel1.IsValid() && (!panel2.IsInitialized || panel2.IsValid());
	}

	// Determines if specified player used more than once in this cell
	private Player FindDuplicate( Player player )
	{
		int count = 0;

		// Panel 1
		if ( panel1.HasPlayer( player ) )
		{
			count++;
		}

		// Panel 2
		if ( panel2.IsInitialized && panel2.HasPlayer( player ) )
		{
			count++;
		}

		// Duplicate if more than 1
		return (count > 1) ? player : null;
	}

	/* Event Callbacks */

	// User selected entry 1/2 segment
	private void OnSelected( string key )
	{
		// Entry 1
		if ( key == OneKey )
		{
			panel1.IsVisible = true;
			panel2.IsVisible = false;
		}
		// Entry 2
		else
		{
			// Lazy layout
			if ( !panel2.IsInitialized )
			{
				panel2.Init( Color );
				panel2.Update();
			}

			panel2.IsVisible = true;
			panel1.IsVisible = false;
		}

		UpdateLayout();
	}

	/* Event Callbacks */

	// Underlying cell panel data changed, notify listener
	private void OnChanged()
	{
		Changed?.Invoke();
	}

	/* Layout */

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

		// Prevent layout too early
		if ( IsInitialized )
		{
			ClearAll();

			LayoutCommon();
		}

		// Update children
		panel1.UpdateLayout( type );

		if ( panel2.IsInitialized )
		{
			panel2.UpdateLayout( type );
		}
	}

	// Dynamic layout for all configurations
	private void LayoutCommon()
	{
		double dim = DXDevice.GetScreenDim();

		bool ios = DXDevice.IsIOS;
		bool tablet = DXDevice.IsTablet;

		// Spacing
		Padding = 0;
		RowSpacing = 0;
		ColumnSpacing = 0;

		double pad = (dim * 0.015);

		double zoneHt = (dim * 0.055);
		double zoneSize = (dim * 0.028);

		double segmentWd = (dim * (tablet ? 0.030 : 0.026));
		double segmentHt = (dim * 0.025);
		double segmentFont = (dim * 0.017);

		// 2 columns
		AddStarColumn( 35 );			// 0: zone
		AddStarColumn( 65 );			// 1: segments

		// 2 rows
		AddFixedRow( zoneHt );			// 0: zone
		AddStarRow();                   // 1: panels

		// Zone
		zoneLbl.FontSize = zoneSize;
		zoneLbl.Margin = ios ? -5 : -10;

		Fill( DXColors.Light4, 0, 0 );
		Add( zoneLbl, 0, 0 );

		// Segment
		segmentBar.SegmentWd = segmentWd;
		segmentBar.SegmentHt = segmentHt;
		segmentBar.SegmentFontSize = segmentFont;
		segmentBar.Margin = new Thickness( pad, (tablet ? 0 : 10), pad, 0 );

		segmentBar.UpdateStyle();

		Add( segmentBar, 1, 0 );

		// Panels (in z-order)
		if ( panel2.IsInitialized )
		{
			Add( panel2, 0, 1, 2, 1 );
		}

		Add( panel1, 0, 1, 2, 1 );
	}
}

//
