Game/DebugTools.cs
namespace BlockParty;

/// <summary>
/// DEBUG-ONLY helpers, gated entirely behind <c>Game.IsEditor</c> (standalone builds never run
/// any of this). None of it is part of the faithful shipping game — it just makes manual testing
/// easier. Currently: left-click a block to press a random one of its still-pressable sides
/// (handy for forcing blocks through their phases).
/// </summary>
public static class DebugTools
{
	/// <summary>Per-frame debug hook for the gameplay stage. Call from <see cref="GameManager.OnUpdate"/>.</summary>
	public static void TickGameStage( GameStage stage, CameraComponent camera )
	{
		if ( stage is null || camera is null ) return;

		if ( !Game.IsEditor ) return;

		if ( !Input.Pressed( "CursorClick" ) ) return;

		// Orthographic camera looking straight down -Z onto the XY plane: a screen-pixel ray is
		// parallel to the view axis, so its origin XY already is the logical pixel under the cursor
		// (1 world unit = 1 logical px, camera centred on the playfield).
		var ray = camera.ScreenPixelToRay( Mouse.Position );
		var p = new Vector2( ray.Position.x, ray.Position.y );

		// foreach ( var b in stage.GetBlocks() )
		// {
		// 	if ( b.IsDead || !b.GetRect().Touches( p ) ) continue;
		// 	PressRandomPressableSide( b );
		// 	break;
		// }
	}

	/// <summary>Press one random side that's currently pressable (not pressed, spiked, or switching).
	/// COSMETIC Rng: this is out-of-sim meddling, so it must not burn an authoritative draw and shift
	/// the run's whole Rng stream on top of the un-replayable press itself.</summary>
	static void PressRandomPressableSide( Block block )
	{
		var candidates = new List<Direction>();
		foreach ( var dir in Globals.GetAllDirections() )
		{
			if ( !block.IsSidePressed( dir ) && !block.HasSpikes( dir ) && !block.IsSwitchingSide( dir ) )
				candidates.Add( dir );
		}

		if ( candidates.Count == 0 ) return;
		var side = candidates[Rng.CosmeticInt( 0, candidates.Count )];
		block.PressSide( side );
		Log.Info( $"[debug] pressed {side} side of {block.BlockType} — this live run's replay will NOT reproduce it (debug presses aren't recorded)." );
	}
}