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

using DXLib.Data;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Represents one cell in a 3x2 grid of lineup positions. Each cell defines a zone (1-6, LIB 1/2), player, jersey number,
 * and position. The cell can also be used to represent one of the optional liberos. Cells can be empty. 
 */ 
public class LineupStarterCell : LineupPanelCell
{
	/* Constants */
	private static double ImageSize;

	// Colors
	private readonly Color EmptyColor = DXColors.Light1;
	private readonly Color NormalColor = DXColors.Light2;

	/* Properties */
	public Player Player { get; private set; }
	public string Position { get; private set; }
	public bool IsAltNumber { get; private set; }

	public bool IsEmpty => (Player == null);
	public bool IsLibero => (Zone >= Lineup.LiberoZone1);

	/* Fields */
	private DXLabel zoneLbl;
	private DXImageArea imageArea;

	private DXLabel firstLbl;
	private DXLabel lastLbl;
	private DXLabel fullLbl;

	private DXNumberButton numberBtn;
	private DXButton positionBtn;
	private DXLabel positionLbl;

	/* Methods */

	// NO UI in constructor
	public LineupStarterCell( int zone ) : base( zone )
	{}

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

		BackgroundColor = EmptyColor;

		bool wide = DXDevice.IsTabletWide;

		// Zone
		zoneLbl = new DXLabel
		{
			Text = IsLibero ? $"{DXString.GetUpper( "lineup.lib" )} {Zone - Lineup.BaseEntries}" : Zone.ToString(),

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

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

		// Icon/Image
		imageArea = new DXImageArea
		{
			IsVisible = false,
			DefaultIcon = "player"
		};

		imageArea.SetImage( (ImageSource)null );

		// First Name
		firstLbl = new DXLabel
		{
			TextColor = DXColors.Dark1,
			Font = DXFonts.RobotoBold,
		};

		// Last Name
		lastLbl = new DXLabel
		{
			TextColor = DXColors.Dark1,
			Font = DXFonts.RobotoBold,
		};

		// Full Name (widescreen only)
		if ( wide )
		{
			fullLbl = new DXLabel
			{
				TextColor = DXColors.Dark1,
				Font = DXFonts.RobotoBold,
				FontSize = 17
			};
		}

		// Jersey Number 
		numberBtn = new DXNumberButton
		{
			IsVisible = false,
			IsDisabled = !IsEditEnabled,

			DisabledOpacity = 1.0,
			HasShadow = IsEditEnabled,
			
			Font = DXFonts.OswaldBold,
			
			IsSticky = true,
			ButtonTapped = OnNumberTapped,

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

		numberBtn.Init();
		
		// Position (non-libero)
		positionBtn = new DXButton
		{
			IsVisible = false,
			IsDisabled = !IsEditEnabled,
			
			DisabledOpacity = 1.0,
			HasShadow = IsEditEnabled,

			Type = DXButton.ButtonType.Positive,
			Font = DXFonts.Roboto,

			IsSticky = true,
			ButtonTapped = OnPositionTapped,

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

		positionBtn.Init();
		
		// Position (libero)
		positionLbl = new DXLabel
		{
			IsVisible = false,

			Text = DXString.GetUpper( "lineup.libero" ),
			TextColor = DXColors.Dark4,
			Font = DXFonts.RobotoBold,

			Vertical = LayoutOptions.Center
		};

		IsInitialized = true;
	}

	/* Entry */

	// Populates cell from lineup entry
	public void SetEntry( LineupEntry entry )
	{
		Player = entry.Player;
        Position = (IsLibero && !IsEmpty) ? Lineup.LiberoKey : (Lineup.IsPositionEmpty( entry.Position ) ? null : entry.Position);
		IsAltNumber = entry.IsAltNumber;
	}

	// Populates cell from menu selected player
	public void SetPlayer( Player player )
	{
		Player = player;

		// Clear position
		if ( player != null )
		{
			Position = Lineup.GetNewPosition( player, Position );
		}

		Update();
	}

	/* Update */

	// Updates cell UI with current values
	public override void Update()
	{
		Color color = IsEmpty ? Organization.DefaultColor : Color;

		// Color indicates empty
		BackgroundColor = IsEmpty ? EmptyColor : NormalColor;

		// Image
		imageArea.IsVisible = !IsEmpty;
		imageArea.Color = color;
		imageArea.SetImage( Player?.ImageUrl );

		// Name
		firstLbl.Text = Player?.FirstName!;
		lastLbl.Text = Player?.LastName!;

		if ( DXDevice.IsTabletWide )
		{
			fullLbl.Text = Player?.FullName!;
		}

		// Number
		numberBtn.IsVisible = !IsEmpty;
		numberBtn.Text = Player?.GetNumber( IsAltNumber );
		numberBtn.ButtonColor = color;
		
		numberBtn.IsDisabled = !IsEditEnabled || IsEmpty || (Player is { HasAltNumber: false });

		// Position

		// Libero has static text, all others have at least '?' button
		if ( !IsLibero )
		{
			positionBtn.Text = Position?.ToUpper();
		}

		positionBtn.IsVisible = !IsEmpty && !IsLibero;
		positionLbl.IsVisible = !IsEmpty && IsLibero;
	}

    /* Event Callbacks */

    // Used to handle either down or tap
    protected override void HandleTouch( Point touch )
    {
        // Do not handle number/position buttons
        if ( IsEmpty || (!positionBtn.Contains( touch ) && !numberBtn.Contains( touch )) )
        {
            base.HandleTouch( touch );
        }
    }

    // NUMBER

    // User tapped jersey number
    private void OnNumberTapped( object sender )
	{
		// Only valid if multiple numbers
		if ( Player.HasAltNumber )
		{
			string num = Player.Number;
			string alt = Player.AltNumber;

			// Build number list
			List<DXItem> list =
			[
				new DXItem { Key = LineupEntry.NumberKey, Value = num },
				new DXItem { Key = LineupEntry.AltNumberKey, Value = alt }
			];

			// Show menu (highlight current value)
			DXMenu numMenu = new()
			{
				Title = "lineup.number",
				MenuWd = 100,

				ItemSelected = OnNumberSelected,
				Cancelled = OnNumberCancelled
			};

			string selected = Player.GetNumber( IsAltNumber );

			numMenu.SetItems( list, selected );
			numMenu.ShowFromView( numberBtn );
		}
	}

	// User selected number from popup menu
	private void OnNumberSelected( DXItem item )
	{
		// User may have cancelled
		if ( item != null )
		{
			IsAltNumber = (item.Key == LineupEntry.AltNumberKey);

			numberBtn.Text = item.Value;
		}

		numberBtn.Reset();

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

	// User cancelled number selection
	private void OnNumberCancelled()
	{
		numberBtn.Reset();
	}

	// POSITION

	// User tapped position
	private void OnPositionTapped( object sender )
	{
		// Show menu (highlight current value)
		DXMenu posMenu = new()
		{
			Title = "lineup.position",
			MenuWd = 240,

			ItemSelected = OnPositionSelected,
			Cancelled = OnPositionCancelled
		};

		posMenu.SetItems( Lineup.GetPositions(), Position );
		posMenu.ShowFromView( positionBtn );
	}

	// User selected position from popup menu
	private void OnPositionSelected( DXItem item )
	{
		// User may have cancelled
		if ( item != null )
		{
			Position = item.Key;
			positionBtn.Text = item.Key.ToUpper();
		}

		positionBtn.Reset();

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

	// User cancelled position selection
	private void OnPositionCancelled()
	{
		positionBtn.Reset();
	}

	/* Layout */

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

		ClearAll();

		// Special handling for widescreen landscape
		if ( DXDevice.IsTabletWide && (type == LayoutType.Landscape) )
		{
			LandscapeWide();
		}
		else
		{
			LayoutCommon();
		}
	}

	// Dynamic layout for all configurations except widescreen landscape
	private void LayoutCommon()
	{
		bool tablet = DXDevice.IsTablet;
		bool ios = DXDevice.IsIOS;
		bool land = DXDevice.IsLandscape();

		double wd = DXDevice.GetScreenWd();
		double dim = DXDevice.GetScreenDim();

		// Spacing
		Padding = 0;
		RowSpacing = tablet ? (ios ? (wd * (land ? 0.003 : 0.005)) : 1) : (dim * 0.002);
		ColumnSpacing = 0;

		double pad = tablet ? (wd * (land ? 0.008 : 0.014)) : (dim * 0.004);

		// Component sizes
		double lineHt = tablet ? (wd * (land ? (ios ? 0.020 : 0.022) : 0.035)) : (dim * (ios ? 0.018 : 0.020));
		double numSize = tablet ? (wd * (land ? 0.029 : 0.045)) : (dim * 0.028);
		double numHt = (numSize + pad);

		// Font size
		double nameSize = tablet ? (wd * (land ? 0.017 : (ios ? 0.025 : 0.022))) : (dim * (ios ? 0.014 : 0.016));
		double zoneSize = tablet ? (IsLibero ? (wd * 0.030) : (wd * 0.041)) : (dim * (IsLibero ? 0.020 : 0.028));
		double numberSize = tablet ? (wd * (land ? 0.016 : 0.022)) : (dim * 0.014);

		ImageSize = tablet ? (land ? (wd * 0.050) : 60) : (dim * 0.050);

		// Zone
		zoneLbl.FontSize = zoneSize;
		zoneLbl.Margin = ios ? 0 : -5;
		
		// Icon/Image
		imageArea.SetSize( ImageSize, ImageSize, 1.0 );

		// First Name
		firstLbl.IsVisible = true;
		firstLbl.Margin = new Thickness( pad, (ios ? (pad - RowSpacing - 2) : 1), pad, 0 );
		firstLbl.FontSize = nameSize;
		
		// Last Name
		lastLbl.IsVisible = true;
		lastLbl.Margin = new Thickness( pad, 0, pad, 0 );
		lastLbl.FontSize = nameSize;
		
		if ( DXDevice.IsTabletWide )
		{
			fullLbl.IsVisible = false;
		}

		double topY = -((pad / 2) + 1);

		// Jersey Number
		numberBtn.Size = numSize;
		numberBtn.FontSize = numberSize;
		numberBtn.Margin = new Thickness( pad, topY, 0, 5 );
		
		// Position (non-libero)
		positionBtn.FontSize = tablet ? (wd * (ios ? (land ? 0.014 : 0.017) : (land ? 0.013 : 0.014))) : 12;
		positionBtn.Margin = new Thickness( (tablet ? 10 : 5), topY, 0, 5 );
		positionBtn.SetSize( (tablet ? (wd * (land ? 0.044 : 0.055)) : 35), (tablet ? (wd * (land ? 0.025 : 0.035)) : 20) );
		
		// Position (libero)
		positionLbl.FontSize = tablet ? (wd * (land ? 0.014 : 0.018)) : 12;
		positionLbl.Margin = new Thickness( pad, (topY + 5), pad, pad );
		
		// 4 rows
		AddFixedRow( ImageSize );		// 0: zone, image
		AddFixedRow( lineHt );			// 1: first
		AddFixedRow( lineHt );			// 2: last
		AddFixedRow( numHt );			// 3: number, position

		// 3 columns
		AddFixedColumn( numHt );		// 0: zone, number
		AddStarColumn();				// 1: zone, position
		AddFixedColumn( ImageSize );	// 2: image
		
		Fill( DXColors.Light4, 0, 0, 2, 1 );
		
		// Add components
		Add( zoneLbl, 0, 0, 2, 1 );
		Add( imageArea, 2, 0 );
		Add( firstLbl, 0, 1, 3, 1 );
		Add( lastLbl, 0, 2, 3, 1 );
		Add( numberBtn, 0, 3 );
		Add( positionBtn, 1, 3, 2, 1 );
		Add( positionLbl, 1, 3, 2, 1 );
	}

	// Landscape (16:10)
	private void LandscapeWide()
	{
		double dim = DXDevice.GetScreenDim();

		// Spacing
		Padding = new Thickness( 0, 0, 0, 5 );
		RowSpacing = 2;
		ColumnSpacing = 0;

		ImageSize = 60;

		double badgeSize = (dim * 0.028);
		double numSize = (dim * 0.016);

		double margin = 10;
		double posMargin = 15;

		double btnWd = (dim * 0.040);
		double btnHt = (badgeSize * 0.80);

		// Zone
		zoneLbl.FontSize = IsLibero ? 24 : 32;
		zoneLbl.Margin = DXUtils.Top( -5 );
		
		// Icon/Image
		imageArea.SetSize( ImageSize, ImageSize, 0.80 );
		
		// Full Name
		firstLbl.IsVisible = false;
		lastLbl.IsVisible = false;

		fullLbl.Margin = margin;
		fullLbl.IsVisible = true;
		
		// Jersey Number 
		numberBtn.FontSize = numSize;
		numberBtn.Margin = new Thickness( margin, 0, 0, RowSpacing );
		numberBtn.TextAdjustY = -4;
		numberBtn.Size = badgeSize;

		Margin = new Thickness( (margin - 5), 1, 0, 0 );

		// Position (non-libero)
		positionBtn.Margin = new Thickness( posMargin, 0, 0, 0 );
		positionBtn.SetSize( btnWd, btnHt );

		// Position (libero)
		positionLbl.Margin = new Thickness( posMargin, -3, 0, 0 );
		
		// 3 rows
		AddFixedRow( ImageSize );       // 0: zone, image
		AddStarRow();                   // 1: first, last
		AddFixedRow( badgeSize );      	// 2: number, position

		// 3 columns
		AddFixedColumn( badgeSize );    // 0: number
		AddStarColumn();				// 1: position
		AddFixedColumn( ImageSize );    // 2: image
		
		// Add components
		Fill( DXColors.Light4, 0, 0, 2, 1 );
		
		Add( zoneLbl, 0, 0, 2, 1 );
		Add( imageArea, 2, 0 );
		Add( fullLbl, 0, 1, 3, 1 );
		Add( numberBtn, 0, 2 );
		Add( positionBtn, 1, 2, 2, 1 );
		Add( positionLbl, 1, 2, 2, 1 );
	}
}

//
