Editor/Floor/ArchApproachPart.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;

namespace Sunless.Architecture;

public enum ApproachKind {
	Steps,
	Ramp
}

// WHAT THE CLIMB LANDS ON. A house's own plinth is the default and was the only answer: the approach seated against
// the nearest exterior wall and climbed to that storey's floor. A podium is the other thing worth arriving at - a
// drive up onto a hardstand, steps up onto a terrace - and there the podium GIVES WAY: its coping breaks over the
// mouth, so the two decks run together instead of the drive meeting a lip it cannot cross.
//
// APPEND-ONLY: a plan on disk names these by ordinal.
public enum ApproachAgainst {
	// Whichever is nearer to the drag. What an author means almost always, and what nothing had to say before.
	Auto,
	Foundation,
	Platform
}

// HOW THE DRIVE'S WALL IS COURSED, and it is the MATERIAL's question rather than the geometry's: cast concrete
// follows the rake the way the trim over it does, and brick cannot - a bricklayer lays level courses and steps
// them, whatever the wall is holding back.
//
// APPEND-ONLY: a plan on disk names these by ordinal.
public enum ApproachMapping {
	Raked,
	Level
}

// What carries the climb inside a rising walkway link.
public enum WalkwayInterior {
	None,
	Stairs,
	Ramp
}

// Both measured from grade to the same floor.
public sealed class ArchApproachPart : IArchPainted, IArchNamed {
	public int Id { get; set; }
	public string Name { get; set; } = "Approach";
	public ApproachKind Kind { get; set; } = ApproachKind.Steps;
	// 0 finds the one it points at - name it only when two roads face the wall.
	public int RoadId { get; set; }
	// Wider at the kerb so a car can turn in off a moving lane.
	public float Splay { get; set; } = 36f;
	// 0 takes the kit's default.
	public int SplaySegments { get; set; }

	// On the wall face, running OUT from the building.
	public Vector2 Origin { get; set; }
	public float Yaw { get; set; }
	public float Width { get; set; } = 48f;
	public List<ArchCurveNode> Nodes { get; set; } = new();

	// Derived from rise and slope unless authored here.
	public float Run { get; set; }
	public bool Kerbs { get; set; } = true;
	public bool Rails { get; set; }

	// The flanks and the lip wear the SKIRT of whatever the drive ran off - a podium's own side, a house's plinth -
	// and only the surface driven over keeps the deck. Off puts the deck's material on every face of it.
	public bool Skirted { get; set; } = true;

	public ApproachMapping Mapping { get; set; } = ApproachMapping.Raked;

	// The author's PREFERENCE, kept whatever the drag resolved to, so a re-dragged approach seats the same way again.
	public ApproachAgainst Against { get; set; } = ApproachAgainst.Auto;

	// The podium it actually seated on, where it seated on one. Stored rather than searched for, because the podium's
	// own coping has to know to break over this mouth and a search would have to guess which approach was its.
	public int PlatformId { get; set; }

	public ArchPalette Palette { get; set; } = new();

	public bool OnPlatform => PlatformId != 0;

	public bool IsSpline => Nodes.Count >= 2;

	public ArchCurve Curve() => ArchCurve.Of( Nodes );
}