Editor/Data/ArchKit.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;

namespace Sunless.Architecture;

public sealed class ArchKit {
	public string Name { get; set; } = "default";

	public ArchCollisionMode Physics { get; set; } = ArchCollisionMode.Solids;
	public bool Shadows { get; set; } = true;

	public float GridSize { get; set; } = 32f;
	// Read through ArchLap, never here.
	public float ContactBite { get; set; } = 0.4f;
	public float GroundClearance { get; set; } = 2f;
	public float TerrainPadding { get; set; } = 48f;
	public float WallHeight { get; set; } = 128f;
	public float WallThickness { get; set; } = 8f;
	public float FloorThickness { get; set; } = 8f;
	public float CeilingThickness { get; set; } = 12f;
	public float FoundationDepth { get; set; } = 24f;
	public float FoundationOversize { get; set; } = 2f;
	public float FoundationRise { get; set; } = 18f;

	public float BreakJitter { get; set; } = 6f;
	public float FalseInteriorDepth { get; set; } = 24f;

	public float RampSlope { get; set; } = 0.15f;
	public float RampThickness { get; set; } = 5f;
	public float RampKerbHeight { get; set; } = 5f;
	public float RampKerbWidth { get; set; } = 4f;

	public float CasingWidth { get; set; } = 4f;
	public float CasingDepth { get; set; } = 1.5f;
	public float BaseboardHeight { get; set; } = 6f;
	public float BaseboardDepth { get; set; } = 1.5f;
	public float WallBandHeight { get; set; } = 4f;
	public float WallBandDepth { get; set; } = 1.5f;
	public float WallCapHeight { get; set; } = 6f;
	public float DentilWidth { get; set; } = 2.2f;
	public float DentilGap { get; set; } = 2.2f;
	public float DentilDrop { get; set; } = 3f;
	public float SillDepth { get; set; } = 3f;
	public float SillThickness { get; set; } = 2f;

	public float GrilleBar { get; set; } = 0.9f;
	public float GrilleGap { get; set; } = 5f;
	public float GrilleProud { get; set; } = 1.5f;
	public float GrilleFrame { get; set; } = 1.6f;

	public float LeafSlat { get; set; } = 1.4f;
	public float LeafGap { get; set; } = 0.7f;
	public float LeafProud { get; set; } = 0.6f;
	public float LeafThickness { get; set; } = 1.6f;

	public float HoodProjection { get; set; } = 5f;
	public float HoodHeight { get; set; } = 4.5f;
	public float HoodOverhang { get; set; } = 4f;
	public float HoodCorbel { get; set; } = 3f;
	public float HoodCorbelDrop { get; set; } = 7f;
	public float PedimentRise { get; set; } = 11f;

	public float AwningValance { get; set; } = 8f;
	public float AwningScallop { get; set; } = 9f;
	public float AwningThickness { get; set; } = 1.2f;

	public float ThresholdProud { get; set; } = 0.6f;
	public float ThresholdLap { get; set; } = 2f;

	public float SidingCourse { get; set; } = 7f;
	public float SidingProud { get; set; } = 1.4f;

	public float SheetPitch { get; set; } = 9f;
	public float SheetCrest { get; set; } = 3.5f;
	public float SheetProud { get; set; } = 1.2f;

	public float FloorBoardWidth { get; set; } = 6f;
	public float FloorBoardGap { get; set; } = 0.25f;
	public float FloorBoardThickness { get; set; } = 1.2f;
	public float FloorBoardLength { get; set; } = 96f;

	public float WainscotHeight { get; set; } = 38f;
	public float WainscotProud { get; set; } = 1.1f;
	public float WainscotStile { get; set; } = 3.5f;
	public float WainscotBay { get; set; } = 26f;
	public float ChairRailHeight { get; set; } = 2.6f;
	public float ChairRailDepth { get; set; } = 2.4f;

	public float FrameFace { get; set; } = 2.6f;
	public float FrameDepth { get; set; } = 3.4f;
	public float FrameSetback { get; set; } = 1.6f;
	public float SashFace { get; set; } = 2.2f;
	public float SashDepth { get; set; } = 1.6f;
	public float GlazingBar { get; set; } = 0.8f;

	public float PorchDeckThickness { get; set; } = 2.5f;
	public float PorchPostSize { get; set; } = 7f;
	public float PorchBeamDepth { get; set; } = 9f;
	public float PorchRailHeight { get; set; } = 34f;
	public float PorchCeilingThickness { get; set; } = 2f;
	public float PorchFriezeHeight { get; set; } = 7f;
	public float PorchFriezeDepth { get; set; } = 2f;
	public float PorchFlashingHeight { get; set; } = 6f;
	public float RoofRafterDepth { get; set; } = 9f;
	public float RoofRafterWidth { get; set; } = 3.4f;
	public float RoofRafterSpacing { get; set; } = 60f;
	public float RoofPurlinDepth { get; set; } = 4f;
	public float RoofPurlinWidth { get; set; } = 2.6f;
	public float RoofPurlinSpacing { get; set; } = 44f;

	public float PorchRafterDepth { get; set; } = 5f;
	public float PorchRafterWidth { get; set; } = 2.4f;
	public float PorchRafterSpacing { get; set; } = 36f;
	public float PorchBraceSize { get; set; } = 3.2f;
	public float PorchBraceRake { get; set; } = 1f;
	public float BalusterSpacing { get; set; } = 5.5f;
	public float BalusterGap { get; set; } = 2.2f;
	public float BalusterScale { get; set; } = 1f;
	public int BalusterSides { get; set; } = 5;

	public float PicketWidth { get; set; } = 3.5f;
	public float PicketGap { get; set; } = 2.4f;
	public float PicketThickness { get; set; } = 1.2f;
	public float FencePostSize { get; set; } = 5f;
	public float FenceRailDepth { get; set; } = 2.4f;
	public float FenceRailHeight { get; set; } = 3.2f;

	public float PalisadeWidth { get; set; } = 1.6f;
	public float PalisadeGap { get; set; } = 4.5f;
	public float PalisadeThickness { get; set; } = 1.2f;

	public float PrecastPostDepth { get; set; } = 7f;
	public float PrecastPostWidth { get; set; } = 6f;
	public float PrecastSlotDepth { get; set; } = 1.8f;
	public float PrecastJoint { get; set; } = 0.3f;
	public float PrecastPlinthProud { get; set; } = 0.9f;
	public float DropperThickness { get; set; } = 0.8f;
	public float WireThickness { get; set; } = 0.25f;
	public float CatenarySag { get; set; } = 0.06f;
	public float RetainingBatter { get; set; } = 0.08f;

	public float PavementFall { get; set; } = 1.2f;
	public float DroppedKerb { get; set; } = 0.8f;
	public float KerbTransition { get; set; } = 24f;
	public int CrossoverSegments { get; set; } = 8;
	public float EdgeLineInset { get; set; } = 8f;
	public float ZebraBar { get; set; } = 18f;
	public float ZebraGap { get; set; } = 18f;
	public float RoadPadding { get; set; } = 96f;
	public float RoadInset { get; set; } = 4f;
	public float JunctionRadius { get; set; } = 180f;
	public float JunctionSpread { get; set; } = 240f;
	public float JunctionLevel { get; set; } = 30f;
	public float PierEmbedment { get; set; } = 12f;
	public float PierClearance { get; set; } = 24f;

	public float RoofThickness { get; set; } = 6f;
	public float RoofPitch { get; set; } = 30f;
	public float RoofOverhang { get; set; } = 16f;
	public float FasciaHeight { get; set; } = 8f;

	public float RoofGuardBay { get; set; } = 96f;
	public float RoofGuardPost { get; set; } = 3f;

	public float SolidGuardThickness { get; set; } = 6f;
	public float SolidGuardCoping { get; set; } = 2.5f;
	public float SolidGuardProud { get; set; } = 1.2f;

	public float PlantHeight { get; set; } = 40f;
	public float PlantWidth { get; set; } = 16f;

	public float GutterBracketSpacing { get; set; } = 96f;
	public float DownpipeBracketSpacing { get; set; } = 48f;
	public float DownpipeWallGap { get; set; } = 1f;

	public float LadderBar { get; set; } = 2.5f;
	public float LadderBracketSpacing { get; set; } = 60f;
	public float LadderCageSpacing { get; set; } = 36f;
	public float LadderCageReach { get; set; } = 30f;

	public float BalconyReach { get; set; } = 36f;
	public float BalconySlab { get; set; } = 5f;
	public float BalconyRail { get; set; } = 40f;
	public float EscapeLanding { get; set; } = 48f;
	public float EscapeWidth { get; set; } = 36f;
	public float ConduitBracketSpacing { get; set; } = 60f;

	public float StepRise { get; set; } = 8f;
	public float StepGoing { get; set; } = 12f;
	public float StairWidth { get; set; } = 48f;
	public float StringerThickness { get; set; } = 3f;
	public float StringerDepth { get; set; } = 14f;
	public float HandrailHeight { get; set; } = 36f;
	public float StairHeadroom { get; set; } = 80f;
	public float NewelSize { get; set; } = 4.5f;
	public float NewelRise { get; set; } = 6f;
	public float StairBalusterSpacing { get; set; } = 5f;
	public float StairWallGap { get; set; } = 10f;
	public float StairCornerReach { get; set; } = 96f;
	public float StairWalkClearance { get; set; } = 60f;

	public float WellTrimProud { get; set; } = 0.75f;
	public float WellTrimDepth { get; set; } = 3.5f;

	public float DoorLeafThickness { get; set; } = 3f;
	public float DoorUndercut { get; set; } = 0.5f;

	public List<ArchOpeningPreset> Openings { get; set; }
	public List<ArchWallPreset> Walls { get; set; }
	public List<ArchProfile> Profiles { get; set; }
	public List<ArchRoadLine> RoadLines { get; set; }

	// Lazy-stocked — a kit from before this shelf existed has no list
	List<ArchCorniceStyle> cornices;

	public List<ArchCorniceStyle> Cornices {
		get => cornices ??= ArchShelved.Ships<ArchCorniceStyle>( ArchShelf.Cornices );
		set => cornices = value;
	}

	List<ArchCabinetType> cabinets;

	public List<ArchCabinetType> Cabinets {
		get => cabinets ??= ArchShelved.Ships<ArchCabinetType>( ArchShelf.Cabinets );
		set => cabinets = value;
	}
	public ArchPalette Palette { get; set; } = new();

	public ArchKit() {
		var shelves = ArchCatalogs.Load();

		Openings = shelves.Ships<ArchOpeningPreset>( ArchShelf.Openings );
		Walls = shelves.Ships<ArchWallPreset>( ArchShelf.Walls );
		Profiles = shelves.Ships<ArchProfile>( ArchShelf.Profiles );
		RoadLines = shelves.Ships<ArchRoadLine>( ArchShelf.RoadLines );
	}

	public ArchOpeningPreset FindOpening( string name ) {
		return Openings.FirstOrDefault( preset => string.Equals( preset.Name, name, StringComparison.OrdinalIgnoreCase ) )
			?? Openings.FirstOrDefault();
	}

	public ArchRoadLine FindRoadLine( string name ) {
		return string.IsNullOrWhiteSpace( name )
			? null
			: RoadLines.FirstOrDefault( line => string.Equals( line.Name, name, StringComparison.OrdinalIgnoreCase ) );
	}

	public ArchProfile FindProfile( string name ) {
		return Profiles.FirstOrDefault( profile => string.Equals( profile.Name, name, StringComparison.OrdinalIgnoreCase ) )
			?? Profiles.FirstOrDefault();
	}

	public ArchCorniceStyle FindCornice( string name ) {
		return string.IsNullOrWhiteSpace( name )
			? null
			: Cornices.FirstOrDefault( style => string.Equals( style.Name, name, StringComparison.OrdinalIgnoreCase ) );
	}
}