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

namespace iStatVball3;

/*
 * Implementation of the scoreboard area for the RallyFlow engine.
 */
public class RallyScore : RecordScore
{
	/* Constants */
	private const int MaxDividers = 8;

	/* Events */
	public Action<double,double> FaultTapped { get; set; }

	/* Properties */
	public override bool IsFaultDisabled { set => DisableFault( value ); }

	// Used for anchoring popup to fault button
	public override Rect FaultBounds => faultBtn.Bounds;

	// Special embedded sync mode?
	public bool IsSyncMode => rallyParent.IsSyncMode;

	/* Fields */

	// Fault button behavior
	private bool faultFlyout;

	// UI controls
	private readonly DrawerIcon faultBtn;
	private readonly List<DrawerDivider> dividers;

	// External ref
	private readonly RallyEngine rallyParent;

	/* Methods */

	// Creates all controls, dynamic layout occurs later
	public RallyScore( RecordEngine parent ) : base( parent )
	{
		rallyParent = (RallyEngine)parent;

		/* Controls */

		// Fault
		faultBtn = new DrawerIcon( this )
		{
			Title = "score.fault",
			Resource = "fault",
			Color = DXColors.Negative,

			ButtonTapped = OnFaultTapped
		};

		faultBtn.Init();
		
		// Undo
		UndoStack.IsSyncMode = rallyParent.IsSyncMode;

		// Dividers
		dividers = new List<DrawerDivider>( MaxDividers );

		for ( int i = 0; i < MaxDividers; i++ )
		{
			dividers.Add( new DrawerDivider( this ) );
		}
	}

	// Makes specified number dividers visible, rest are hidden
	private void ShowDividers( int count )
	{
		for ( int i = 0; i < dividers.Count; i++ )
		{
			dividers[i].IsVisible = (i < count);
		}
	}

	/* Update */

	// Updates points for both teams at end of rally (or side switch)
	public override void UpdateScore( int scoreA, int scoreB )
	{
		base.UpdateScore( scoreA, scoreB );

		// Update mobile buttons
		parent.UpdateScore( scoreA, scoreB );

		// Poll current user setting
		faultFlyout = ((RallyState)sm).HasFaults();
	}

	// Updates team names on each side of court
	public override void UpdateTeams( string teamA, string teamB )
	{
		base.UpdateTeams( teamA, teamB );

		// Update mobile
		parent.UpdateTeams( teamA, teamB );
	}

	// Updates scorecard color for team on each side of court
	public override void UpdateTeamColors( Color colorA, Color colorB )
	{
		base.UpdateTeamColors( colorA, colorB );

		// Update mobile
		parent.UpdateTeamColors( colorA, colorB );
	}

	/* Disable */

	// RallyFlow never disables score
	public override void DisableScore( bool disabled )
	{
		base.DisableScore( false );
	}

	// Enables/disables fault button
	private void DisableFault( bool disabled )
	{
		faultBtn.IsDisabled = disabled;
		parent.IsFaultDisabled = disabled;
	}

	// Enables/disables undo button
	protected override void DisableUndo( bool disabled )
	{
		base.DisableUndo( disabled );

		parent.IsUndoDisabled = disabled;
	}

	/* Event Handling */

	// Fault
	private void OnFaultTapped()
	{
		// Fault acts like normal button when flyouts off
		if ( !faultFlyout )
		{
			// Faults start/end same point
			FaultTapped?.Invoke( Stats.FaultX, Stats.FaultY );
		}
	}

	// Pause
	protected override void OnPauseTapped()
	{
		// Close drawers/overlays
		parent?.CloseDrawers();

		base.OnPauseTapped();
	}

	// User confirmed end of set
	protected override async void OnEndConfirmed()
	{
		// Persist set end data
		await parent.End( Score1, Score2 );

		base.OnEndConfirmed();
	}

	/* Layout */

	// Landscape (4:3) [dynamic]
	protected override void Landscape()
	{
		bool sync = rallyParent.IsSyncMode;
		bool ios = DXDevice.IsIOS;
		bool wide = DXDevice.IsTabletWide;

		Thickness safeArea = DXDevice.SafeArea();
		
		double boundsWd = LayoutWidth;
		
		// Padding
		double pad = (boundsWd * 0.014);
		double syncPad = (boundsWd * 0.007);
		double safeTop = pad + (sync ? 0 : safeArea.Top); 
		
		Padding = new Thickness( pad, safeTop, pad, pad );

		double wd = (boundsWd - Padding.HorizontalThickness);

		// Layout constants
		double btnY = (wd * (sync ? 0.050 : 0.033));
		double btnWd = (wd * 0.047);

		double spaceWd = (wd * 0.019);
		double scoreWd = (wd * 0.076);

		double colWd = (btnWd + spaceWd);
		double totalWd = (btnWd * 11) + (spaceWd * 12) + (scoreWd * 2);

		double titleFont = (wd * 0.013);
		double numberFont = (wd * 0.031);
		double teamFont = (wd * 0.019);
		double scoreFont = (wd * 0.050);
		double setFont = (wd * 0.020);

		double logoWd = (wd * 0.206);
		double logoHt = (wd * 0.023);

		double barHt = (wd * 0.014);

		/* Controls */

		double logoY = sync ? syncPad : 0;
		
		// Logo
		logoBar.SetSize( logoWd, logoHt );
		SetBounds( logoBar, 0, logoY, logoWd, logoHt );

		// Toolbar
		toolBar.Spacing = sync ? 3 : (wide ? 4 : 2);
		toolBar.IconHt = sync ? 17 : 25;

		double toolBarWd = toolBar.GetWidth();
		double toolBarHt = toolBar.GetHeight();

		double toolBarX = (wd - toolBarWd + ToolBar.Pad);
		double toolbarY = sync ? syncPad : 0;

		SetBounds( toolBar, toolBarX, (toolbarY - 5), toolBarWd, toolBarHt );

		double x1 = ((wd - totalWd) / 2) + 2;

		// Pause
		pauseBtn.TitleSize = titleFont;
		pauseBtn.Layout( x1, btnY, btnWd );

		double x2 = (x1 + colWd);

		// End
		endBtn.TitleSize = titleFont;
		endBtn.Layout( x2, btnY, btnWd );

		double x3 = (x2 + colWd);

		// Switch
		switchBtn.TitleSize = titleFont;
		switchBtn.Resource = "switch_horiz";

		switchBtn.Layout( x3, btnY, btnWd );

		double x4 = (x3 + colWd);

		// Timeout A
		timeoutsABtn.AdjustX = sync ? -2 : (ios ? -2 : (wide ? -5 : -3));
		timeoutsABtn.TitleSize = titleFont;
		timeoutsABtn.NumberSize = numberFont;

		timeoutsABtn.Layout( x4, btnY, btnWd );

		double x5 = (x4 + colWd);
		double scoreY = sync ? (pad + 5) : 1;

		// Score A
		scoreABtn.BarHt = barHt;
		scoreABtn.TeamSize = teamFont;
		scoreABtn.ScoreSize = scoreFont;

		scoreABtn.Layout( x5, scoreY, scoreWd, scoreWd );

		double x6 = (x5 + scoreWd + spaceWd);

		// Sets A
		setsABtn.TitleSize = titleFont;
		setsABtn.NumberSize = numberFont;

		setsABtn.Layout( x6, btnY, btnWd );

		double x7 = (x6 + colWd);
		double setY = sync ? syncPad : 0;
		double setSize = (wd * 0.031);

		double arrowSize = (setSize - 10);
		double arrowY = setY + ((setSize - arrowSize) / 2);

		// Possession A
		possABtn.Resource = "arrow_left";
		possABtn.Size = arrowSize;

		SetBounds( possABtn, (x7 - spaceWd - arrowSize), arrowY, arrowSize, arrowSize );

		// Set Number
		double setX = (x7 + ((btnWd - setSize) / 2));

		setBtn.NumberSize = setFont;
		setBtn.Layout( setX, setY, setSize );

		// Fault
		faultBtn.TitleSize = titleFont;
		faultBtn.Layout( x7, btnY, btnWd );

		double x8 = (x7 + colWd);

		// Possession B
		possBBtn.Resource = "arrow_right";
		possBBtn.Size = arrowSize;

		SetBounds( possBBtn, x8, arrowY, arrowSize, arrowSize );

		// Sets B
		setsBBtn.TitleSize = titleFont;
		setsBBtn.NumberSize = numberFont;

		setsBBtn.Layout( x8, btnY, btnWd );

		double x9 = (x8 + colWd);

		// Score B
		scoreBBtn.BarHt = barHt;
		scoreBBtn.TeamSize = teamFont;
		scoreBBtn.ScoreSize = scoreFont;

		scoreBBtn.Layout( x9, scoreY, scoreWd, scoreWd );

		double x10 = (x9 + scoreWd + spaceWd);

		// Timeout B
		timeoutsBBtn.AdjustX = (ios ? -2 : (wide ? -5 : -3));
		timeoutsBBtn.TitleSize = titleFont;
		timeoutsBBtn.NumberSize = numberFont;

		timeoutsBBtn.Layout( x10, btnY, btnWd );

		double x11 = (x10 + colWd);

		// Undo
		undoBtn.TitleSize = titleFont;
		undoBtn.Layout( x11, btnY, btnWd );

		double x12 = (x11 + btnWd + (spaceWd * 0.5));
		
		double undoWd = (btnWd * 3) + (DXDevice.IsTabletWide ? -10 : 20);
		double undoHt = (wd * 0.064);

		// Undo Stack
		UndoStack.FontSize = (wd * (wide ? 0.010 : 0.012));
		UndoStack.Spacing = (wd * (ios ? 0.003 : (wide ? 0.002 : 0.001)));
		UndoStack.Margin = DXUtils.Top( ios ? -1 : -3 );

		SetBounds( UndoStack, x12, btnY, undoWd, undoHt );

		// Dividers not needed
		ShowDividers( 0 );
	}

	// Widescreen Landscape (16:10)
	protected override void WideLandscape()
	{
		Landscape();
	}

	// Portrait (3:4) [dynamic]
	protected override void Portrait()
	{
		bool ios = DXDevice.IsIOS;

		Padding = 0;

		// Layout constants
		double wd = LayoutWidth;
		double ht = DXDevice.GetScreenHt() - DXDevice.GetSafeTop();

		double btnWd = (ht * 0.041);
		double btnHt = (ht * 0.056);

		double spaceWd = (ht * 0.007);
		double spaceHt = (ht * 0.003);
		double spaceHt2 = (spaceHt * 2);

		double scoreWd = (ht * 0.089);
		double scoreHt = (ht * 0.072);

		double dividerWd = wd;
		const double dividerHt = 1;

		double colWd = (btnWd + spaceWd);
		double rowHt = (btnHt + spaceHt);

		double x1 = (ht * 0.012);
		double x2 = (x1 + colWd);
		double x3 = (x2 + colWd);
		double x4 = (x3 + colWd);

		double titleFont = (ht * 0.012);

		/* Controls */

		// Toolbar
		toolBar.Spacing = 8;

		double toolBarWd = toolBar.GetWidth();
		double toolBarHt = toolBar.GetHeight();

		double toolBarX = (LayoutWidth - toolBarWd - 7);
		double toolBarY = spaceHt;

		SetBounds( toolBar, toolBarX, toolBarY, toolBarWd, toolBarHt );

		double div0Y = (toolBarY + toolBarHt + spaceHt2);

		// Divider
		dividers[0].Layout( 0, div0Y, dividerWd, dividerHt );

		double row2Ht = (rowHt * 2);

		double logoHt = (ht * 0.040);
		double logoY = (toolBarY + toolBarHt + ((row2Ht - toolBarHt - logoHt) / 2) + 1);

		// Logo
		logoBar.SetSize( (ht * 0.180), (ht * 0.021) );
		SetBounds( logoBar, 0, logoY, wd, logoHt );

		double div1Y = (toolBarY + row2Ht);

		// Divider
		dividers[1].Layout( 0, div1Y, dividerWd, dividerHt );

		// Teambar space
		double teamBarHt = (ht * 0.208) - (DXDevice.IsTabletWide ? 108 : 0);
		double div2Y = (div1Y + dividerHt + teamBarHt);

		// Divider
		dividers[2].Layout( 0, div2Y, dividerWd, dividerHt );

		double teamFont = (ht * 0.018);
		double numberFont = (ht * 0.025);

		double scoreAY = (div2Y + dividerHt + spaceHt2);
		double scoreHt2 = ((scoreHt + teamFont) * 0.37);
		double scoreAY2 = (scoreAY + scoreHt2);

		// Timeout A
		timeoutsABtn.TitleSize = titleFont;
		timeoutsABtn.NumberSize = numberFont;
		timeoutsABtn.AdjustX = -6;

		timeoutsABtn.Layout( x1, scoreAY2, btnWd );

		double scoreFont = (ht * 0.051);
		double scoreFullHt = (ht * 0.098);

		// Score A
		scoreABtn.TeamSize = teamFont;
		scoreABtn.ScoreSize = scoreFont;

		scoreABtn.Layout( x2, scoreAY, scoreWd, scoreHt );

		// Sets A
		setsABtn.TitleSize = titleFont;
		setsABtn.NumberSize = numberFont;

		setsABtn.Layout( x4, scoreAY2, btnWd );

		double possAY = (scoreAY + scoreFullHt + spaceHt);

		double setSize = (btnWd - spaceHt);

		double arrowSize = (setSize - (ht * 0.015));
		double arrowX = (wd - arrowSize) / 2;

		// Possession A
		possABtn.Resource = "arrow_up";
		possABtn.Size = arrowSize;

		SetBounds( possABtn, arrowX, possAY, arrowSize, arrowSize );

		double setAY = (possAY + arrowSize + spaceHt);
		double setAY2 = (setAY - (ht * 0.018));

		double btnWd2 = (btnWd + 5);

		// Fault
		faultBtn.TitleSize = titleFont;
		faultBtn.Layout( x1, setAY2, btnWd2 );

		double col2Wd = (btnWd * 2) + spaceWd;
		double centerX = x2 + ((col2Wd - btnWd - 5) / 2);

		// Set Number
		setBtn.NumberSize = (ht * 0.020);
		setBtn.Layout( centerX, setAY, setSize );

		double undoX = (x4 - 5);

		// Undo
		undoBtn.TitleSize = titleFont;
		undoBtn.Layout( undoX, setAY2, btnWd2 );

		double possBY = (setAY + btnWd + spaceHt);

		// Possession B
		possBBtn.Resource = "arrow_down";
		possBBtn.Size = arrowSize;

		SetBounds( possBBtn, arrowX, possBY, arrowSize, arrowSize );

		double scoreBY = (possBY + arrowSize + spaceHt2);
		double scoreBY2 = (scoreBY + scoreHt2);

		// Timeout B
		timeoutsBBtn.TitleSize = titleFont;
		timeoutsBBtn.NumberSize = numberFont;
		timeoutsBBtn.AdjustX = -6;

		timeoutsBBtn.Layout( x1, scoreBY2, btnWd );

		// Score B
		scoreBBtn.TeamSize = teamFont;
		scoreBBtn.ScoreSize = scoreFont;

		scoreBBtn.Layout( x2, scoreBY, scoreWd, scoreHt );

		// Sets B
		setsBBtn.TitleSize = titleFont;
		setsBBtn.NumberSize = numberFont;

		setsBBtn.Layout( x4, scoreBY2, btnWd );

		double div3Y = (scoreBY + scoreFullHt + spaceHt);

		// Divider
		dividers[3].Layout( 0, div3Y, dividerWd, dividerHt );

		// Teambar space
		double div4Y = (div3Y + dividerHt + teamBarHt);

		// Divider
		dividers[4].Layout( 0, div4Y, dividerWd, dividerHt );

		double stackY = (div4Y + dividerHt + (ios ? (spaceHt2 - 3) : spaceHt));
		double stackHt = (btnHt + (ios ? 3 : 10));

		// Undo stack
		UndoStack.FontSize = (ht * 0.012);
		UndoStack.Spacing = (ios ? 2 : 1);

		SetBounds( UndoStack, x1, stackY, wd, stackHt );

		double div5Y = (stackY + stackHt + spaceHt2);

		// Divider
		dividers[5].Layout( 0, div5Y, dividerWd, dividerHt );

		double switchY = (div5Y + dividerHt + spaceHt2);

		// Switch
		switchBtn.Resource = "switch_vert";
		switchBtn.TitleSize = titleFont;
		switchBtn.AdjustX = ios ? -1 : -2;

		switchBtn.Layout( x1, switchY, btnWd );

		// Pause
		pauseBtn.TitleSize = titleFont;
		pauseBtn.Layout( centerX, switchY, btnWd );

		// End
		endBtn.TitleSize = titleFont;
		endBtn.Layout( x4, switchY, btnWd );

		// All dividers used
		ShowDividers( 6 );
	}

	// Widescreen Portrait (10:16)
	protected override void WidePortrait()
	{
		Padding = 0;

		// Layout constants
		double wd = LayoutWidth;
		double ht = LayoutHeight;

		const double btnWd = 44;
		const double btnHt = 60;

		const double spaceWd = 12;
		const double spaceHt = 3;
		const double spaceHt2 = (spaceHt * 2);

		const double colWd = (btnWd + spaceWd);
		const double rowHt = (btnHt + spaceHt);

		const double scoreWd = (btnWd * 2) + spaceWd;
		const double scoreHt = 74;

		const double x1 = 10;
		const double x2 = (x1 + colWd);
		const double x3 = (x2 + colWd);

		const double row2Ht = (rowHt * 2);

		const double setSize = btnWd;
		const double arrowSize = (setSize - 25);
		const double scoreFullHt = 100;

		double dividerWd = wd;
		const double dividerHt = 1;

		const double titleFont = 12;
		const double numberFont = 26;

		const double totalHt = (rowHt * 6) + (scoreFullHt * 2) + btnHt + (arrowSize * 2) + (dividerHt * 8) + (spaceHt * 14);
		double padHt = (ht - totalHt) / 2;

		/* Controls */

		const double startY = 0;

		// Divider
		dividers[0].Layout( 0, startY, dividerWd, dividerHt );

		toolBar.Spacing = 0;

		double toolBarWd = toolBar.GetWidth();
		double toolBarHt = toolBar.GetHeight();

		double toolBarX = (LayoutWidth - toolBarWd);
		const double toolBarY = (startY + dividerHt + 7);

		// Toolbar
		SetBounds( toolBar, toolBarX, toolBarY, toolBarWd, toolBarHt );

		double div1Y = (toolBarY + toolBarHt + spaceHt);

		// Divider
		dividers[1].Layout( 0, div1Y, dividerWd, dividerHt );

		double logoHt = (row2Ht - toolBarHt - dividerHt);
		double logoY = (div1Y + dividerHt);

		// Logo
		logoBar.SetSize( 140, 66 );
		SetBounds( logoBar, 0, logoY, wd, logoHt );

		double div2Y = (logoY + logoHt);

		// Divider
		dividers[2].Layout( 0, div2Y, dividerWd, dividerHt );

		double div3Y = (div2Y + dividerHt + padHt);

		// Divider
		dividers[3].Layout( 0, div3Y, dividerWd, dividerHt );

		double timeAY = (div3Y + dividerHt + spaceHt2);

		// Timeout A
		timeoutsABtn.AdjustX = -5;
		timeoutsABtn.TitleSize = titleFont;
		timeoutsABtn.NumberSize = numberFont;

		timeoutsABtn.Layout( x2, timeAY, btnWd );

		// Sets A
		setsABtn.TitleSize = titleFont;
		setsABtn.NumberSize = numberFont;
		setsABtn.Layout( x3, timeAY, btnWd );

		double scoreAY = (timeAY + rowHt + spaceHt);

		const double teamFont = 18;
		const double scoreFont = 52;

		// Score A
		scoreABtn.TeamSize = teamFont;
		scoreABtn.ScoreSize = scoreFont;

		scoreABtn.Layout( x2, scoreAY, scoreWd, scoreHt );

		double possAY = (scoreAY + scoreFullHt + spaceHt);

		const double col2Wd = (btnWd * 2) + spaceWd;
		double arrowX = x2 + ((col2Wd - arrowSize) / 2);

		// Possession A
		possABtn.Resource = "arrow_up";
		possABtn.Size = arrowSize;

		SetBounds( possABtn, arrowX, possAY, arrowSize, arrowSize );

		double setY = (possAY + arrowSize + spaceHt);
		double setMidY = (setY + (setSize / 2));

		double centerX = x2 + ((col2Wd - btnWd) / 2);

		// Set Number
		setBtn.NumberSize = 20;
		setBtn.Layout( centerX, setY, setSize );

		double possBY = (setY + btnWd + spaceHt);

		// Possession B
		possBBtn.Resource = "arrow_down";
		possBBtn.Size = arrowSize;

		SetBounds( possBBtn, arrowX, possBY, arrowSize, arrowSize );

		double faultY = (setMidY - btnHt);

		// Fault
		faultBtn.TitleSize = titleFont;
		faultBtn.Layout( x1, faultY, btnWd );

		double undoY = (setMidY + (spaceHt * 2));

		// Undo
		undoBtn.TitleSize = titleFont;
		undoBtn.IsVisible = true;
		undoBtn.Layout( x1, undoY, btnWd );

		double scoreBY = (possBY + arrowSize + spaceHt);

		// Score B
		scoreBBtn.TeamSize = teamFont;
		scoreBBtn.ScoreSize = scoreFont;

		scoreBBtn.Layout( x2, scoreBY, scoreWd, scoreHt );

		double timeBY = (scoreBY + scoreFullHt + spaceHt);

		// Timeout B
		timeoutsBBtn.AdjustX = -5;
		timeoutsBBtn.TitleSize = titleFont;
		timeoutsBBtn.NumberSize = numberFont;

		timeoutsBBtn.Layout( x2, timeBY, btnWd );

		// Sets B
		setsBBtn.TitleSize = titleFont;
		setsBBtn.NumberSize = numberFont;
		setsBBtn.Layout( x3, timeBY, btnWd );

		double div4Y = (timeBY + rowHt + spaceHt);

		// Divider
		dividers[4].Layout( 0, div4Y, dividerWd, dividerHt );

		double div5Y = (div4Y + dividerHt + padHt);

		// Divider
		dividers[5].Layout( 0, div5Y, dividerWd, dividerHt );

		double stackY = (div5Y + spaceHt2 - 1);

		const double stackWd = ((colWd * 3) - spaceWd);
		const double stackHt = (btnHt + 5);

		// Undo Stack
		UndoStack.FontSize = (wd * 0.010);
		UndoStack.Spacing = (wd * 0.002);
		UndoStack.Margin = DXUtils.Top( -3 );

		SetBounds( UndoStack, x1, stackY, stackWd, stackHt );

		double div6Y = (stackY + stackHt + spaceHt2 + 1);

		// Divider
		dividers[6].Layout( 0, div6Y, dividerWd, dividerHt );

		double switchY = (div6Y + dividerHt + spaceHt2);

		// Switch
		switchBtn.Resource = "switch_vert";
		switchBtn.TitleSize = titleFont;
		switchBtn.Layout( x1, switchY, btnWd );

		// Pause
		pauseBtn.TitleSize = titleFont;
		pauseBtn.Layout( x2, switchY, btnWd );

		// End
		endBtn.TitleSize = titleFont;
		endBtn.Layout( x3, switchY, btnWd );

		double div7Y = (ht - dividerHt);

		// Divider
		dividers[7].Layout( 0, div7Y, dividerWd, dividerHt );

		// 8 dividers
		ShowDividers( 8 );
	}

	// Mobile Landscape
	protected override void MobileLandscape()
	{
		bool ios = DXDevice.IsIOS;
		Thickness safeArea = DXDevice.SafeArea();
		
		Padding = new Thickness( 10, (8 + (ios ? 0 : safeArea.Top)), 10, 14 );

		// Layout constants
		const int numCols = 14;

		double wd = LayoutWidth - Padding.HorizontalThickness;
		double ht = LayoutHeight;

		double spaceWd = (wd / (ios ? 105 : 75));

		double btnWd = (wd - (spaceWd * 12)) / numCols;
		double btnY = (ht - Padding.Bottom - btnWd - (ios ? 18 : 36));

		double colWd = (btnWd + spaceWd);

		double scoreWd = (colWd * 1.50);
		double scoreHt = (ios ? 80 : (ht * 0.61));

		double numberFont = (ios ? 30 : 32);

		/* Controls */

		double logoWd = (colWd * 3);
		double logoHt = (logoWd / 8.8);

		// Logo
		logoBar.SetSize( logoWd, logoHt );
		SetBounds( logoBar, 0, 0, logoWd, logoHt );

		toolBar.Spacing = (ios ? 0 : 5);

		double toolBarWd = toolBar.GetWidth();
		double toolBarHt = toolBar.GetHeight();

		double toolBarX = (wd - toolBarWd);

		// Toolbar
		SetBounds( toolBar, toolBarX, 0, toolBarWd, toolBarHt );

		const double x1 = 0;

		// Pause
		pauseBtn.Layout( x1, btnY, btnWd );

		double x2 = (x1 + colWd);

		// End
		endBtn.Layout( x2, btnY, btnWd );

		double x3 = (x2 + colWd);

		// Switch
		switchBtn.Resource = "switch_horiz";
		switchBtn.Layout( x3, btnY, btnWd );

		double x4 = (x3 + colWd);

		// Timeout A
		timeoutsABtn.AdjustX = 0;
		timeoutsABtn.NumberSize = numberFont;

		timeoutsABtn.Layout( x4, btnY, btnWd );

		double x5 = (x4 + colWd);
		double scoreY = (ios ? 2 : 0);

		const double teamFont = 17;
		const double scoreFont = 54;

		// Score A
		scoreABtn.TeamSize = teamFont;
		scoreABtn.ScoreSize = scoreFont;

		scoreABtn.Layout( x5, scoreY, scoreWd, scoreHt );

		double x6 = (x5 + scoreWd + spaceWd);

		// Sets A
		setsABtn.NumberSize = numberFont;
		setsABtn.Layout( x6, btnY, btnWd );

		double x7 = (x6 + colWd);

		double setSize = (ios ? 33 : 30);

		double arrowSize = (setSize - 10);
		double arrowY = ((setSize - arrowSize) / 2) - 2;

		// Possession A
		possABtn.Resource = "arrow_left";
		possABtn.Size = arrowSize;

		SetBounds( possABtn, (x7 - spaceWd - arrowSize), arrowY, arrowSize, arrowSize );

		// Set Number
		double setX = (x7 + ((btnWd - setSize) / 2));

		setBtn.NumberSize = (ios ? 20 : 17);
		setBtn.Layout( setX, 0, setSize );

		// Fault
		faultBtn.Layout( x7, btnY, btnWd );

		double x8 = (x7 + colWd);

		// Possession B
		possBBtn.Resource = "arrow_right";
		possBBtn.Size = arrowSize;

		SetBounds( possBBtn, x8, arrowY, arrowSize, arrowSize );

		// Sets B
		setsBBtn.NumberSize = numberFont;
		setsBBtn.Layout( x8, btnY, btnWd );

		double x9 = (x8 + colWd);

		// Score B
		scoreBBtn.TeamSize = teamFont;
		scoreBBtn.ScoreSize = scoreFont;

		scoreBBtn.Layout( x9, scoreY, scoreWd, scoreHt );

		double x10 = (x9 + scoreWd + spaceWd);

		// Timeout B
		timeoutsBBtn.AdjustX = 0;
		timeoutsBBtn.NumberSize = numberFont;

		timeoutsBBtn.Layout( x10, btnY, btnWd );

		// Undo
		undoBtn.IsVisible = false;

		double x11 = (x10 + colWd);

		double undoY = btnY + (ios ? 0 : 5);
		double undoWd = (colWd * 3) - (spaceWd * 3) + (ios ? 0 : 5);
		double undoHt = btnWd + undoBtn.TitleHt + 5;

		// Undo Stack
		SetBounds( UndoStack, x11, undoY, undoWd, undoHt );

		// Dividers NOT needed
		ShowDividers( 0 );
	}

	// Mobile Portrait
	protected override void MobilePortrait()
	{
		Padding = 0;

		// Layout constants
		double wd = LayoutWidth;
		double ht = LayoutHeight;

		const double btnWd = 44;
		const double btnHt = 60;

		const double spaceWd = 5;
		const double spaceHt = 3;
		const double space2Ht = (spaceHt * 2);

		const double colWd = (btnWd + spaceWd);
		const double rowHt = (btnHt + spaceHt);

		const double scoreWd = (btnWd * 2) + spaceWd;
		const double scoreHt = 74;

		const double x1 = 10;
		const double x2 = (x1 + colWd);
		const double x3 = (x2 + colWd);
		const double x4 = (x3 + colWd);

		const double row2Ht = (rowHt * 2);

		const double setSize = btnWd;
		const double arrowSize = (setSize - 25);

		const double partialHt = 35;
		const double scoreFullHt = 100;

		double dividerWd = wd;
		const double dividerHt = 1;

		const double totalHt = (rowHt * 4) + (scoreFullHt * 2) + btnHt + (arrowSize * 2) + (dividerHt * 6) + (spaceHt * 9);
		double padHt = (ht - totalHt) / 2;

		const double numberFont = 26;

		/* Controls */

		toolBar.Spacing = 8;

		double toolBarWd = toolBar.GetWidth();
		double toolBarHt = toolBar.GetHeight();

		double toolBarX = (LayoutWidth - 12 - toolBarWd);
		const double toolBarY = 2;

		// Toolbar
		SetBounds( toolBar, toolBarX, toolBarY, toolBarWd, toolBarHt );

		double div0Y = (toolBarY + toolBarHt + spaceHt + 15);

		// Divider
		dividers[0].Layout( 0, div0Y, dividerWd, dividerHt );

		const double div1Y = (toolBarY + row2Ht);

		// Divider
		dividers[1].Layout( 0, div1Y, dividerWd, dividerHt );

		const double logoHt = 41;
		double logoY = (div0Y + ((div1Y - div0Y) / 2) - (logoHt / 2));

		// Logo (after div for centering)
		logoBar.SetSize( 175, 20 );
		SetBounds( logoBar, 0, logoY, wd, logoHt );

		double div2Y = (toolBarY + row2Ht + padHt);

		// Divider
		dividers[2].Layout( 0, div2Y, dividerWd, dividerHt );

		double scoreAY = (div2Y + dividerHt + (spaceHt * 2));
		double scoreAY2 = (scoreAY + partialHt);

		// Timeout A
		timeoutsABtn.AdjustX = 0;
		timeoutsABtn.NumberSize = numberFont;

		timeoutsABtn.Layout( x1, scoreAY2, btnWd );

		const double teamFont = 18;
		const double scoreFont = 52;

		// Score A
		scoreABtn.TeamSize = teamFont;
		scoreABtn.ScoreSize = scoreFont;

		scoreABtn.Layout( x2, scoreAY, scoreWd, scoreHt );

		// Sets A
		setsABtn.NumberSize = numberFont;
		setsABtn.Layout( x4, scoreAY2, btnWd );

		double possAY = (scoreAY + scoreFullHt + spaceHt);
		double arrowX = (wd - arrowSize) / 2;

		// Possession A
		possABtn.Resource = "arrow_up";
		possABtn.Size = arrowSize;

		SetBounds( possABtn, arrowX, possAY, arrowSize, arrowSize );

		double setAY = (possAY + arrowSize + spaceHt);
		double setAY2 = (setAY - 18);

		const double btnWd2 = (btnWd + 5);

		// Fault
		faultBtn.Layout( x1, setAY2, btnWd2 );

		const double col2Wd = (btnWd * 2) + spaceWd;
		const double centerX = x2 + ((col2Wd - btnWd - 5) / 2);

		// Set Number
		setBtn.NumberSize = 24;
		setBtn.Layout( centerX, setAY, setSize );

		const double undoX = (x4 - 5);

		// Undo
		undoBtn.IsVisible = true;
		undoBtn.Layout( undoX, setAY2, btnWd2 );

		double possBY = (setAY + btnWd + spaceHt);

		// Possession B
		possBBtn.Resource = "arrow_down";
		possBBtn.Size = arrowSize;

		SetBounds( possBBtn, arrowX, possBY, arrowSize, arrowSize );

		double scoreBY = (possBY + arrowSize + spaceHt);
		double scoreBY2 = (scoreBY + partialHt);

		// Timeout B
		timeoutsBBtn.AdjustX = 0;
		timeoutsBBtn.NumberSize = numberFont;

		timeoutsBBtn.Layout( x1, scoreBY2, btnWd );

		// Score B
		scoreBBtn.TeamSize = teamFont;
		scoreBBtn.ScoreSize = scoreFont;

		scoreBBtn.Layout( x2, scoreBY, scoreWd, scoreHt );

		// Sets B
		setsBBtn.NumberSize = numberFont;
		setsBBtn.Layout( x4, scoreBY2, btnWd );

		double div3Y = (scoreBY2 + rowHt + spaceHt);

		// Divider
		dividers[3].Layout( 0, div3Y, dividerWd, dividerHt );

		double div4Y = (div3Y + padHt);

		// Divider
		dividers[4].Layout( 0, div4Y, dividerWd, dividerHt );

		double stackY = (div4Y + space2Ht + 3);

		double stackWd = wd;
		double stackHt = btnHt;

		// Undo Stack
		SetBounds( UndoStack, x1, stackY, stackWd, stackHt );

		double div5Y = (stackY + stackHt + spaceHt);

		// Divider
		dividers[5].Layout( 0, div5Y, dividerWd, dividerHt );

		double switchY = (div5Y + dividerHt + space2Ht);

		// Switch
		switchBtn.Resource = "switch_vert";
		switchBtn.Layout( x1, switchY, btnWd );

		// Pause
		pauseBtn.Layout( centerX, switchY, btnWd );

		// End
		endBtn.Layout( x4, switchY, btnWd );

		// 4 dividers
		ShowDividers( 6 );
	}
}

//
