package cat

import "testing"

// WSJT-X "Fake It" against the transmit-window cache.
//
// Fake It keeps the radio on one dial frequency and shifts it only for the
// duration of each over: set the transmit frequency, key, transmit, unkey, set
// it back. The restore is not unconditional — WSJT-X reads the frequency back
// and puts the dial where it believes it should be.
//
// That read lands inside the window where this backend deliberately stops
// polling, because a Kenwood answers "?;" to IF; while it is transmitting and
// treating that as a fault used to drop the whole shared link. The cache
// answers instead. So the cache has to account for frequency SETS made during
// the window, or it describes the dial as it was before the over — and WSJT-X,
// told the radio is already on the receive frequency, has nothing to restore.
//
// This reproduces the sequence from a reported session: the dial stayed on the
// transmit frequency after the first over and every later one started there.
func TestKenwoodFakeItRestoresAfterTransmit(t *testing.T) {
	const (
		rxHz = 7074000 // where the operator is listening
		txHz = 7075500 // where Fake It moves the dial to transmit
	)

	rig := &ts2000{vfoA: rxHz, mode: '2'}
	k := NewKenwood("COM-TEST", 9600, "FT8")
	k.dialPort = dialTo(rig)
	if err := k.Connect(); err != nil {
		t.Fatalf("connect: %v", err)
	}
	defer k.Disconnect()

	if s, err := k.ReadState(); err != nil || s.FreqHz != rxHz {
		t.Fatalf("before the over: %d (err %v) — want %d", s.FreqHz, err, rxHz)
	}

	// The over: shift the dial, then key.
	if err := k.SetFrequency(txHz); err != nil {
		t.Fatalf("set transmit frequency: %v", err)
	}
	if err := k.SetPTT(true); err != nil {
		t.Fatalf("ptt on: %v", err)
	}

	// WSJT-X reads back mid-over. The wire is not polled here — this is the
	// cache talking, and it must not still be saying rxHz.
	s, err := k.ReadState()
	if err != nil {
		t.Fatalf("read during the over: %v", err)
	}
	if s.FreqHz != txHz {
		t.Errorf("during the over the backend reported %d, want %d — "+
			"reporting the pre-over frequency is what stops Fake It restoring the dial", s.FreqHz, txHz)
	}

	if err := k.SetPTT(false); err != nil {
		t.Fatalf("ptt off: %v", err)
	}

	// The restore, once the over is done.
	if err := k.SetFrequency(rxHz); err != nil {
		t.Fatalf("restore: %v", err)
	}
	if rig.vfoA != rxHz {
		t.Errorf("dial left on %d after the over, want %d", rig.vfoA, rxHz)
	}
	if s, err := k.ReadState(); err != nil || s.FreqHz != rxHz {
		t.Errorf("after the over: %d (err %v) — want %d", s.FreqHz, err, rxHz)
	}
}

// Under split the same write must NOT touch the cache: FreqHz means the
// transmit frequency while the write lands on whichever VFO the operator is on,
// so guessing which side moved would put a wrong number in front of the
// operator. A stale one survives only until the next poll.
func TestKenwoodSplitCacheLeftToThePoll(t *testing.T) {
	rig := &ts2000{vfoA: 14025000, vfoB: 14030000, mode: '3', split: true}
	k := NewKenwood("COM-TEST", 9600, "CW")
	k.dialPort = dialTo(rig)
	if err := k.Connect(); err != nil {
		t.Fatalf("connect: %v", err)
	}
	defer k.Disconnect()

	s, err := k.ReadState()
	if err != nil || !s.Split {
		t.Fatalf("split not seen: %+v (err %v)", s, err)
	}
	before := s.FreqHz

	if err := k.SetFrequency(14026000); err != nil {
		t.Fatalf("set: %v", err)
	}
	if k.lastState.FreqHz != before {
		t.Errorf("split cache moved to %d on a VFO write, want it left at %d for the poll",
			k.lastState.FreqHz, before)
	}
}
