/* 
 * 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.Alert;
using DXLib.UI.Layout;
using DXLib.UI.Control.Button;

using DXLib.Utils;

namespace iStatVball3;

/*
 * Represents one substitution/swap panel in a lineup replace cell. The sub/swap includes both the players coming OUT
 * and IN as well as configuration for whether there should be confirmation first and when a swap should occur.
 */
public class LineupReplacePanel : DXGridLayout
{
	/* Events */
	public Action Changed { get; set; }

	/* Properties */
	public Color Color { get; private set; }

	// Already initialized?
	public bool IsInitialized { get; private set; }

	/* Fields */

	// Entries
	private readonly LineupReplaceRow outRow;
	private readonly LineupReplaceRow inRow;

	private LineupReplaceRow selectedRow;

	// Data
	private bool confirm;
	private bool start;

	// UI
	private readonly DXToggleButton confirmBtn;
	private readonly DXToggleButton startBtn;

	// External refs
	private readonly LineupReplace parent;
	private readonly int zone;

	/* Methods */

	// NO UI in constructor
	public LineupReplacePanel( LineupReplace parent, int zone )
	{
		this.parent = parent;
		this.zone = zone;

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

        // Out
        outRow = new LineupReplaceRow( parent, LineupReplaceRow.RowType.Out )
        {
            RowTapped = OnRowTapped,
            Changed = OnChanged
        };

        // In
        inRow = new LineupReplaceRow( parent, LineupReplaceRow.RowType.In )
        {
            RowTapped = OnRowTapped,
            Changed = OnChanged
        };

        // Confirm first?
        confirmBtn = new DXToggleButton()
        {
            Resource = "replace.confirm",
            IsSelected = true,
            Vertical = LayoutOptions.Center,

            ButtonToggled = OnConfirmToggled
        };
        
        confirmBtn.Init();

        // Start or end of possession?
        startBtn = new DXToggleButton()
        {
            Resource = "replace.start",
            IsSelected = true,
            Vertical = LayoutOptions.Center,

            ButtonToggled = OnStartToggled
        };

        startBtn.Init();
        
        // Defaults
        confirm = true;
		start = true;
	}

	// Post construction initialization (components MUST be allocated in constructor)
	public void Init( Color color )
	{
		Color = color;
		BackgroundColor = DXColors.Dark2;

		// Layout rows
		outRow.Init( Color );
		inRow.Init( Color );

		IsInitialized = true;
	}

    /* Entries */

    // Returns replacement entry given current panel configuration (DEEP COPY)
    public LineupEntryReplace GetEntry()
    {
        if ( IsPopulated() )
        {
            return new LineupEntryReplace
            {
                Type = parent.Type,
                Rotation = zone,

                OutEntry = outRow.GetEntry(),
                InEntry = inRow.GetEntry(),

                Confirm = confirm,
                Start = start
            };
        }

        return null;
    }

    // Sets all entry values for this panel
    public void SetEntry( LineupEntryReplace entry )
    {
        confirm = entry.Confirm;
        start = entry.Start;

        // Populate underlying rows
        outRow.SetEntry( entry.OutEntry );
        inRow.SetEntry( entry.InEntry );
        
        Update();
    }

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

        // Out
        if ( !outRow.IsEmpty )
        {
            players.Add( outRow.Player );
        }

        // In
        if ( !inRow.IsEmpty )
        {
            players.Add( inRow.Player );
        }

        return players;
    }

    /* Update */

    // Updates display with current data
    public void Update()
	{
		confirmBtn.IsSelected = confirm;
		startBtn.IsSelected = start;

		// Update rows
		outRow.Update();
		inRow.Update();

		// Update buttons
		UpdateVisible();
	}

	// UI controls only visible if both replace rows populated
	private void UpdateVisible()
	{
		bool visible = IsPopulated();

		confirmBtn.IsVisible = visible;
		startBtn.IsVisible = visible;
	}

	/* Validation */

	// Determines if either row contains specified player
	public bool HasPlayer( Player player )
	{
		return outRow.HasPlayer( player ) || inRow.HasPlayer( player );
	}

	// Determines if specified OUT/IN row contains given player
	public bool HasPlayer( Player player, LineupReplaceRow.RowType type )
	{
		return type switch
		{
			LineupReplaceRow.RowType.Out => outRow.HasPlayer( player ),
			LineupReplaceRow.RowType.In => inRow.HasPlayer( player ),

			_ => false,
		};
	}

	// Are both rows fully populated?
	public bool IsPopulated()
	{
		return !outRow.IsEmpty && !inRow.IsEmpty;
	}

	// Valid if empty or populated without duplicate players
	public bool IsValid()
	{
		bool outEmpty = outRow.IsEmpty;
		bool inEmpty = inRow.IsEmpty;

		// Both empty, valid
		if ( outEmpty && inEmpty )
		{
			return true;
		}
		
		// Both populated
		if ( !outEmpty && !inEmpty )
		{
			// OUT/IN duplicated or invalid, IN must have position
			return !inRow.HasPlayer( outRow.Player ) && inRow.IsValid();
		}
		
		// Only one populated, invalid
		return false;
	}

	/* Utils */

    // Returns row other than specified row
    private LineupReplaceRow GetOtherRow( LineupReplaceRow row )
    {
        return row.Equals( outRow ) ? inRow : outRow;
    }

    // Returns list of players to be displayed in sub/swap menu
    private List<Player> GetMenuPlayers( bool liberos )
    {
        List<Player> players;

        // Swap IN shows only liberos
        if ( liberos )
        {
            players = [ ..parent.Liberos ];
        }
        // Otherwise full roster minus liberos
        else
        {
            players = [ ..parent.Roster ];

            foreach ( Player player in parent.Liberos )
            {
                players.Remove( player );
            }
        }

        return players;
    }

    /* Event Callbacks */

    // User tapped player row
    private void OnRowTapped( LineupReplaceRow row )
	{
		bool liberos = (parent.IsSwap && row.IsIn);

		// Get liberos or full roster
		List<Player> players = GetMenuPlayers( liberos );

		int count = players.Count;

		// Could be missing liberos
		if ( count > 0 )
		{
            // Dynamically create menu
            LineupMenu menu = new( count, true )
            {
                MenuColor = Color,
                
                // Update popup menu
                Header = $"{DXString.GetUpper("lineup.rot")} {zone}",
                HasClear = !row.IsEmpty
            };

            Player otherPlayer = GetOtherRow( row ).Player;
			Player thisPlayer = row.Player;

			// Existing player disabled, player from other row reduced
			menu.SetPlayers( players );
			menu.SetReduced( [ otherPlayer ] );
			menu.SetDisabled( [ thisPlayer ] );

			menu.PlayerSelected = OnPlayerSelected;

			selectedRow = row;

			// Display
			menu.ShowFromView( row );
		}
		else
		{
			DXAlert.ShowError( "replace.swapin", "replace.swapin.lib" );
		} 
	}

	// User selected player from popup, populate data
	private void OnPlayerSelected( Player player, bool cancel )
	{
		selectedRow.SetPlayer( player );

		// Update, notify listener
		OnChanged();
	}

	// Controls become visible when both rows populated
	private void OnChanged()
	{
		UpdateVisible();

		// Notify listener
		Changed?.Invoke();
	}

	// CONFIRM/START

	// User toggled confirmation
	private void OnConfirmToggled( DXToggleButton button )
	{
		confirm = button.IsSelected;

		// Notify listener
		Changed?.Invoke();
	}

	// User toggled possession start
	private void OnStartToggled( DXToggleButton button )
	{
		start = button.IsSelected;

		// Notify listener
		Changed?.Invoke();
	}

	/* Layout */

	// Redraws entire panel
	public override void UpdateLayout( LayoutType type )
	{
		ClearAll();

		bool tablet = DXDevice.IsTablet;
		bool wide = DXDevice.IsWidescreen();
		
		double dim = DXDevice.GetScreenDim();
		double fontSize = (dim * 0.011);

		double btnWd = (dim * (tablet ? (wide ? 0.065 : 0.075) : 0.060));
		double btnHt = (dim * 0.030);

		Padding = 0;
		Margin = 0;

		RowSpacing = 0;
		ColumnSpacing = 3;

		// 3 rows
		AddStarRow( 37 );			// 0: out
		AddStarRow( 37 );			// 1: in
		AddStarRow( 26 );			// 2: buttons

		// 2 columns
		AddStarColumn( 50 );		// 0: confirm
		AddStarColumn( 50 );		// 1: start

		// Rows
		Add( outRow, 0, 0, 3, 1 );
		Add( inRow, 0, 1, 3, 1 );

		// Confirm
		confirmBtn.Margin = 0;
		confirmBtn.FontSize = fontSize;
		confirmBtn.Horizontal = LayoutOptions.End;
		confirmBtn.SetSize( btnWd, btnHt );

		Add( confirmBtn, 0, 2 );

		// Start
		startBtn.Margin = 0;
		startBtn.FontSize = fontSize;
		startBtn.Horizontal = LayoutOptions.Start;
		startBtn.SetSize( btnWd, btnHt );

		Add( startBtn, 1, 2 );

		// Update children
		outRow.UpdateLayout( type );
		inRow.UpdateLayout( type );
	}
}

//
