Editor/Wall/ArchWallModPart.cs
using System;
using System.Collections.Generic;
using Sandbox;

namespace Sunless.Architecture;

// APPEND ONLY — inserting mid-list renumbers every authored modifier after it
public enum ArchWallMod {
	Pilaster,
	Quoin,
	Buttress,
	Indent,
	Sign,
	Awning,
	Course
}

// OnSurface is a placement mode — placed parts always resolve to Outside or Inside
public enum ArchWallSide {
	Outside,
	Inside,
	Both,
	OnSurface
}

public static class ArchWallModKinds {
	public const float PlateHeight = 24f;
	public const float CanopyReach = 34f;

	public static bool Carves( this ArchWallMod kind ) => kind == ArchWallMod.Indent;

	public static bool Coursed( this ArchWallMod kind ) => kind == ArchWallMod.Quoin;

	public static bool Banded( this ArchWallMod kind ) => kind == ArchWallMod.Course;

	public const float CourseHeight = 16f;

	public static bool Tapers( this ArchWallMod kind ) => kind == ArchWallMod.Buttress;

	public static bool Falls( this ArchWallMod kind ) => kind == ArchWallMod.Awning;

	public static bool Plated( this ArchWallMod kind ) => kind is ArchWallMod.Sign or ArchWallMod.Awning;

	public static float Seat( this ArchWallMod kind, float authored, float wallHeight ) {
		if ( !kind.Plated() || authored > 0.5f ) {
			return authored;
		}

		return MathF.Max( 0f, wallHeight - PlateHeight );
	}

	public static float Rise( this ArchWallMod kind, float authored ) {
		if ( !kind.Plated() || authored > 0.5f ) {
			return authored;
		}

		return PlateHeight;
	}

	public static string Piece( this ArchWallMod kind ) => kind switch {
		ArchWallMod.Sign => ArchPieces.Sign,
		ArchWallMod.Awning => ArchPieces.Awning,
		_ => null
	};

	public static float Reach( this ArchWallMod kind, float authored ) {
		return kind.Falls() && authored < CanopyReach ? CanopyReach : authored;
	}

	public static ArchSurface Field( this ArchWallMod kind ) => kind switch {
		ArchWallMod.Indent => ArchSurface.WallBase,
		ArchWallMod.Quoin or ArchWallMod.Course => ArchSurface.WallBase,
		ArchWallMod.Sign => ArchSurface.Sign,
		ArchWallMod.Awning => ArchSurface.Awning,
		_ => ArchSurface.Pillar
	};

	public static string Label( this ArchWallMod kind ) => kind switch {
		ArchWallMod.Pilaster => "Pilaster — an engaged strip standing proud of the elevation",
		ArchWallMod.Quoin => "Quoin — rusticated blocks, alternately long and short",
		ArchWallMod.Buttress => "Buttress — a proud pier leaning back as it climbs",
		ArchWallMod.Sign => "Sign — a proud plate saying what the building was",
		ArchWallMod.Awning => "Awning — a canopy over the shopfront under a scalloped valance",
		ArchWallMod.Course => "Course — level bands across the width, parted by a recessed joint",
		_ => "Indent — a recess bitten out of the outside face"
	};

	public static string Glyph( this ArchWallMod kind ) => kind switch {
		ArchWallMod.Pilaster => "view_column",
		ArchWallMod.Quoin => "grid_view",
		ArchWallMod.Buttress => "signal_cellular_4_bar",
		ArchWallMod.Sign => "label",
		ArchWallMod.Awning => "roofing",
		ArchWallMod.Course => "view_stream",
		_ => "check_box_outline_blank"
	};

	public static string Label( this ArchWallSide side ) => side switch {
		ArchWallSide.Outside => "Outside — stands on the street elevation",
		ArchWallSide.Inside => "Inside — stands in the room",
		ArchWallSide.Both => "Both — a pier reading on either face",
		_ => "On surface — whichever face the drag lands on"
	};

	public static string Glyph( this ArchWallSide side ) => side switch {
		ArchWallSide.Outside => "villa",
		ArchWallSide.Inside => "flip_to_back",
		ArchWallSide.Both => "flip",
		_ => "ads_click"
	};
}

public sealed class ArchWallModPart : IArchPainted, IArchNamed {
	public int Id { get; set; }
	public string Name { get; set; } = "Pilaster";
	public ArchWallMod Kind { get; set; } = ArchWallMod.Pilaster;
	public ArchWallSide Side { get; set; } = ArchWallSide.Outside;
	// Station along the wall run, not a world point — survives the wall being dragged
	public float Along { get; set; }
	public float Width { get; set; } = 16f;
	public float Base { get; set; }
	public float Height { get; set; }
	public float Depth { get; set; } = 3f;
	public float Course { get; set; }
	public float Joint { get; set; }
	public ArchSurface Field { get; set; } = ArchSurface.Pillar;
	public ArchPalette Palette { get; set; } = new();

	public bool Carves => Kind.Carves();

	public float Left => Along - Width * 0.5f;

	public float Right => Along + Width * 0.5f;
}