Editor/Pillar/ArchSpanUi.cs
using System;
using System.Linq;
using Editor;
using Sandbox;

namespace Sunless.Architecture;

public static class ArchSpanUi {
	// The sheet lays both halves in one go; the Pillars sequence asks them as two steps, because picking a form
	// is an answer and typing a section is not.
	public static void Build( ToolSidebarWidget panel, ArchSpanPart span, Action refresh, Action changed ) {
		Form( panel.AddGroup( "Form" ), span, refresh, changed );
		Section( panel.AddGroup( "Section" ), span, changed );
	}

	// Handed step.Chose as its refresh by the sequence and a plain refresh by the sheet - it advances by doing
	// what it already did.
	public static void Form( Layout group, ArchSpanPart span, Action refresh, Action changed ) {
		using var forms = ArchIconGrid.In( group );

		foreach ( var value in Enum.GetValues<PillarSpan>().Where( value => value != PillarSpan.None ) ) {
			var captured = value;

			forms.Pick( $"Span: {Hint( captured )}", $"span_{captured}".ToLowerInvariant(), Glyph( captured ),
				span.Form == captured, () => { span.Form = captured; changed?.Invoke(); refresh?.Invoke(); } );
		}
	}

	public static void Section( Layout group, ArchSpanPart span, Action changed ) {
		group.Add( ArchPartUi.Number( "Thickness (0 takes the piers')", span.Thickness, 0f, value => span.Thickness = value, changed ) );
		group.Add( ArchPartUi.Number( "Drop below the head", span.Drop, 0f, value => span.Drop = value, changed ) );
		group.Add( ArchPartUi.Number( "Springs from floor (0 takes the rise)", span.Springing, 0f, value => span.Springing = value, changed ) );

		if ( span.Form == PillarSpan.Beam ) {
			group.Add( ArchPartUi.Number( "Depth", span.BeamDepth, 18f, value => span.BeamDepth = value, changed ) );

			return;
		}

		group.Add( ArchPartUi.Number( "Rise", span.Rise, 48f, value => span.Rise = value, changed ) );

		if ( span.Form == PillarSpan.Arch ) {
			group.Add( ArchPartUi.Number( "Ring", span.Ring, 10f, value => span.Ring = value, changed ) );
		}

		group.Add( ArchPartUi.Integer( "Segments", span.Segments, 10, value => span.Segments = value, changed ) );
	}

	// What the section step reads back closed: the one dimension the form is judged on, kit stock and all.
	public static string Measured( ArchSpanPart span ) {
		return span.Form == PillarSpan.Beam
			? $"{Stocked( span.BeamDepth, 18f ):0} deep"
			: $"{Stocked( span.Rise, 48f ):0} rise";
	}

	static float Stocked( float value, float stock ) => value > 0f ? value : stock;

	public static string Hint( PillarSpan form ) => form switch {
		PillarSpan.Beam => "a straight block from pier to pier",
		PillarSpan.Arch => "a ring turned between them",
		PillarSpan.Haunch => "a cove filling the corner at each end, with nothing between",
		_ => "nothing between them"
	};

	public static string Glyph( PillarSpan form ) => form switch {
		PillarSpan.Beam => "horizontal_rule",
		PillarSpan.Arch => "bridge",
		PillarSpan.Haunch => "rounded_corner",
		_ => "block"
	};
}