package structs

import "testing"

func TestPerimeter(t *testing.T) {
	rectangle := Rectangle{10.0, 10.0}
	got := Perimeter(rectangle)
	want := 40.0

	if got != want {
		t.Errorf("got %.2f want %.2f", got, want)
	}
}

// %.2f is replaced with %g which will print a more precise decimal number in an error message.

func TestArea(t *testing.T) {

	// Helper function
	checkArea := func(t testing.TB, shape Shape, want float64) {
		t.Helper()
		got := shape.Area()
		if got != want {
			t.Errorf("got %g want %g", got, want)
		}
	}

	t.Run("area rectangle", func(t *testing.T) {
		rectangle := Rectangle{12.0, 6.0}
		checkArea(t, rectangle, 72.0)
	})

	t.Run("area circle", func(t *testing.T) {
		circle := Circle{10}
		checkArea(t, circle, 314.1592653589793)
	})

}

// https://go.dev/wiki/TableDrivenTests are useful when you want to build a list of test cases that can be tested in the same manner.
// They are a great fit when you wish to test various implementations of an interface, or if the data being passed in to a function has lots of different requirements that need testing.
func TestAreaTable(t *testing.T) {

	// "anonymous struct"
	areaTests := []struct {
		name  string
		shape Shape
		want  float64
	}{
		// example showing named arguments. Arguably it is more readable.
		{name: "Rectangle", shape: Rectangle{Width: 12, Height: 6}, want: 72.0},
		{"Circle", Circle{10}, 314.1592653589793},
		{"Triangle", Triangle{12, 6}, 36.0},
	}

	// for _, tt := range areaTests {
	// 	got := tt.shape.Area()
	// 	if got != tt.want {
	// 		// %#v format string will print out our struct with the values in its field
	// 		t.Errorf("%#v got %g want %g", tt, got, tt.want)
	// 	}
	//}

	// Wrap in t.Run for better debug output and test failure identification
	for _, tt := range areaTests {
		t.Run(tt.name, func(t *testing.T) {
			got := tt.shape.Area()
			if got != tt.want {
				t.Errorf("%#v got %g want %g", tt, got, tt.want)
			}
		})
	}

}