UI/CreateScreen.razor
@using System;
@using Sandbox;
@using Sandbox.UI;

@* New gladiator, laid out like the Flash game: name box, look box, stats with -/+, skill points, tick / cross.
   The gladiator himself stands in the 3D hall on the right (World3D shows the draft look). *@
<root class="screen">
	<div class="sas-panel name-panel">
		<div class="sas-label">enter name below</div>
		<TextEntry @ref="NameBox" class="sas-entry" MaxLength=@(20)></TextEntry>
	</div>

	<div class="sas-panel look-panel">
		@foreach ( var row in LookRows )
		{
			var r = row;
			<div class="look-row">
				<div class="sas-label look-name">@r.Name</div>
				<div class="sas-arrow left" onclick=@(() => Change( r.Edit, -1 ))></div>
				<div class="sas-arrow right" onclick=@(() => Change( r.Edit, 1 ))></div>
				<div class="look-value">@r.Value()</div>
			</div>
		}
		<div class="sas-link randomize" onclick=@Randomize>randomize</div>
	</div>

	<div class="sas-panel stats-panel">
		@foreach ( var idx in Profile.StatOrder )
		{
			var i = idx;
			<div class="stat-line" onmouseover=@(() => { Hover = i; StateHasChanged(); }) onmouseout=@(() => { if ( Hover == i ) { Hover = -1; StateHasChanged(); } })>
				<div class="sas-label stat-name">@Profile.StatNames[i].ToLower()</div>
				<div class="stat-value">@(P?.GetStat( i ) ?? 1)</div>
				<div class="sas-pm minus @(CanMinus( i ) ? "" : "off")" onclick=@(() => Minus( i ))></div>
				<div class="sas-pm plus @(P?.StatPoints > 0 ? "" : "off")" onclick=@(() => Plus( i ))></div>
			</div>
		}
	</div>

	<div class="sas-panel points-panel">
		<div class="sas-label">skill points</div>
		<div class="points-number">@(P?.StatPoints ?? 0)</div>
		<div class="points-help">@(Hover >= 0 ? Profile.StatHelp[Hover] : (string.IsNullOrEmpty( Warning ) ? "Spend every point, then tick to begin." : Warning))</div>
	</div>

	<div class="sas-round tick" onclick=@Begin><div class="mark"></div></div>
	<div class="sas-round cross" onclick=@Cancel><div class="mark"></div></div>
</root>

@code
{
	TextEntry NameBox { get; set; }
	Look Draft = Look.Default;
	string Warning;
	int Hover = -1;

	Profile P => Profile.Current;

	record LookRow( string Name, Func<Look, int, Look> Edit, Func<string> Value );

	LookRow[] LookRows => new LookRow[]
	{
		new( "race", ( l, d ) => { l.Race = Wrap( l.Race + d, Catalog.Races.Length ); l.Skin = 0; return l; }, () => Draft.RaceName.ToLower() ),
		new( "skin colour", ( l, d ) => { l.Skin = Wrap( l.Skin + d, Catalog.Races[l.Race].Skins.Length ); return l; }, () => "" ),
		new( "hairstyle", ( l, d ) => { l.Hair = Wrap( l.Hair + d, Catalog.HairCount + 1 ); return l; }, () => Draft.Hair == 0 ? "bald" : "" ),
		new( "hair colour", ( l, d ) => { l.HairColour = Wrap( l.HairColour + d, Catalog.HairColours.Length ); return l; }, () => "" ),
		new( "stubble", ( l, d ) => { l.Beard = Wrap( l.Beard + d, Catalog.BeardCount + 1 ); return l; }, () => Draft.Beard == 0 ? "none" : "" ),
		new( "loincloth", ( l, d ) => { l.Cloth = Wrap( l.Cloth + d, Catalog.ClothColours.Length ); return l; }, () => "" ),
	};

	static int Wrap( int v, int count ) => ((v % count) + count) % count;

	/// <summary>What the 3D gladiator wears while you design him: your rags and club.</summary>
	Look Preview
	{
		get
		{
			var l = Draft;
			l.Chest = 0;
			l.Weapon = 1;
			return l;
		}
	}

	void Change( Func<Look, int, Look> edit, int d )
	{
		Draft = edit( Draft, d );
		StateHasChanged();
	}

	void Randomize()
	{
		var rng = Random.Shared;
		var l = Draft;
		l.Race = rng.Int( 0, Catalog.Races.Length - 1 );
		l.Skin = rng.Int( 0, Catalog.Races[l.Race].Skins.Length - 1 );
		l.Hair = rng.Int( 0, Catalog.HairCount );
		l.HairColour = rng.Int( 0, Catalog.HairColours.Length - 1 );
		l.Beard = rng.Float() < 0.4f ? 0 : rng.Int( 1, Catalog.BeardCount );
		l.Cloth = rng.Int( 0, Catalog.ClothColours.Length - 1 );
		Draft = l;
		StateHasChanged();
	}

	bool CanMinus( int i ) => P is not null && P.GetStat( i ) > Profile.StartStat;

	void Plus( int i )
	{
		GameManager.Instance?.SpendStat( i );
		Warning = null;
		StateHasChanged();
	}

	void Minus( int i )
	{
		GameManager.Instance?.UnspendStat( i );
		StateHasChanged();
	}

	// back to the title without saving (a half-made gladiator must not overwrite your save)
	void Cancel()
	{
		var gm = GameManager.Instance;
		if ( gm.IsValid() ) gm.Screen = GameScreen.Title;
	}

	void Begin()
	{
		if ( P is null ) return;
		if ( P.StatPoints > 0 )
		{
			Warning = "Spend all your skill points first!";
			StateHasChanged();
			return;
		}

		GameManager.Instance?.FinishCreate( NameBox?.Text, Draft );
	}

	public override void Tick()
	{
		base.Tick();
		var w = World3D.Instance;
		if ( w.IsValid() )
		{
			w.HeroLook = Preview;
			w.HeroMood = Mood.Upset;
			w.HeroAnim = "idle";
		}
	}

	protected override int BuildHash() => HashCode.Combine( Draft.Race, Draft.Skin, Draft.Hair, Draft.Beard, Draft.HairColour, Draft.Cloth, Warning, HashCode.Combine( P?.StatPoints, Hover ) );
}