namespace splat;

using Chickensoft.GoDotTest;
using Godot;
using Shouldly;

public class TerrainTest : TestClass
{
    public TerrainTest(Node testScene) : base(testScene) { }

    [Test]
    public void DefaultGroundRepresentsUsableSoil()
    {
        var ground = GroundType.Default();

        ground.ResourceName.ShouldBe("Soil");
        ground.Type.ShouldBe(GroundType.Kind.Soil);
        ground.Friction.ShouldBeGreaterThan(0f);
        ground.Drainage.ShouldBeInRange(0f, 1f);
        ground.FrostSusceptibility.ShouldBeInRange(0f, 1f);
    }

    [Test]
    public void TerrainCreatesPhysicalAndVisualSurfaceWhenSceneHasNone()
    {
        var terrain = new Terrain { Size = 64f };
        TestScene.AddChild(terrain);

        terrain.CollisionLayer.ShouldBe(16u);
        terrain.Ground.ShouldNotBeNull();
        var collision = terrain.GetNode<CollisionShape3D>("CollisionShape3D");
        var mesh = terrain.GetNode<MeshInstance3D>("MeshInstance3D");
        ((BoxShape3D)collision.Shape).Size.ShouldBe(new Vector3(64f, 1f, 64f));
        ((PlaneMesh)mesh.Mesh).Size.ShouldBe(new Vector2(64f, 64f));
        terrain.Free();
    }

    [Test]
    public void AuthoredTerrainSceneCarriesLocalGroundData()
    {
        var scene = GD.Load<PackedScene>("res://src/Environment/Terrain.tscn");
        var first = scene.Instantiate<Terrain>();
        var second = scene.Instantiate<Terrain>();

        first.Ground.GroundName.ShouldBe("Highland Soil");
        ReferenceEquals(first.Ground, second.Ground).ShouldBeFalse();
        first.GetNodeOrNull<CollisionShape3D>("CollisionShape3D").ShouldNotBeNull();
        first.GetNodeOrNull<MeshInstance3D>("MeshInstance3D").ShouldNotBeNull();
        first.Free();
        second.Free();
    }
}
