package kpa

import "testing"

// The reference's own examples, kept as the test. Every one of these strings is
// quoted from the KPA1500 Programming Reference rather than invented here, so a
// change that breaks the decoding fails against the document.
func TestParseTheDocumentedExamples(t *testing.T) {
	t.Run("^WS — forward power and SWR", func(t *testing.T) {
		w, swr, err := parseWS("^WS1204 014;")
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if w != 1204 || swr != 1.4 {
			t.Errorf("got %d W, SWR %.1f; want 1204 W, SWR 1.4", w, swr)
		}
	})

	// A KPA500 sends three digits for the watts. The split is on the space, so
	// the same code reads both amplifiers.
	t.Run("^WS from a KPA500 — three digits", func(t *testing.T) {
		w, swr, err := parseWS("^WS480 021;")
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if w != 480 || swr != 2.1 {
			t.Errorf("got %d W, SWR %.1f; want 480 W, SWR 2.1", w, swr)
		}
	})

	t.Run("^VI — volts in tenths, amps whole", func(t *testing.T) {
		v, a, err := parseVI("^VI513 061;")
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if v != 51.3 || a != 61 {
			t.Errorf("got %.1f V, %d A; want 51.3 V, 61 A", v, a)
		}
	})

	t.Run("^TM — heat sink temperature", func(t *testing.T) {
		c, err := parseInt("^TM045;", "^TM")
		if err != nil || c != 45 {
			t.Errorf("got %d, %v; want 45", c, err)
		}
	})

	t.Run("^OS — operate or standby", func(t *testing.T) {
		for reply, want := range map[string]int{"^OS0;": 0, "^OS1;": 1} {
			got, err := parseInt(reply, "^OS")
			if err != nil || got != want {
				t.Errorf("%s → %d, %v; want %d", reply, got, err, want)
			}
		}
	})

	t.Run("^BN — the K3 band numbering", func(t *testing.T) {
		n, err := parseInt("^BN05;", "^BN")
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if got := BandName(n); got != "20m" {
			t.Errorf("^BN05 → %q, want 20m", got)
		}
		if got := BandName(10); got != "6m" {
			t.Errorf("^BN10 → %q, want 6m", got)
		}
	})
}

// ^FL is HEX. Read as decimal, 90 and 91 — reflected power and "antenna not
// connected" — become 144 and 145 and match nothing at all, so the amplifier
// would be shut down by a fault OpsLog could not name.
func TestFaultCodesAreHex(t *testing.T) {
	code, err := parseFault("^FL91;")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if code != 0x91 {
		t.Fatalf("^FL91 → %d, want %d (0x91)", code, 0x91)
	}
	if name := FaultName(code); name == "" || name == "fault 91" {
		t.Errorf("0x91 should be named, got %q", name)
	}
	if got := FaultName(0); got != "" {
		t.Errorf("no fault should be empty, got %q", got)
	}
	// A code from a firmware newer than this table still says something.
	if got := FaultName(0xAB); got != "fault AB" {
		t.Errorf("unknown code → %q, want \"fault AB\"", got)
	}
}

// Answers to somebody else's question are refused rather than misread. On a
// serial line shared with the amplifier's own utility, or on the first read
// after a reconnect, a stale reply is still in flight.
func TestPayloadRefusesAnotherCommandsAnswer(t *testing.T) {
	if _, _, err := parseWS("^VI513 061;"); err == nil {
		t.Error("a ^VI answer was accepted as ^WS")
	}
	if _, err := parseInt("^TM045;", "^PC"); err == nil {
		t.Error("a ^TM answer was accepted as ^PC")
	}
}
