// Command psttest probes PstRotatorAz's UDP tracking input to discover the wire
// format it expects for the "DXLog.net" tracker. We don't have the spec, so this
// sends a series of labelled candidate datagrams to the target and pauses between
// each so you can watch PstRotatorAz and note which one it reacts to (the band
// filter "Rotate Antenna only for the Selected Bands" changes, or the frequency
// shows in the tracker box).
//
// Setup on the PstRotatorAz side:
//   - Tracker = DXLog.net
//   - Note the UDP port it listens on (commonly 12040) and this PC's IP
//   - In the tracker setup tick a couple of bands so the band filter is visible
//
// Usage:
//
//	go run ./cmd/psttest 192.168.1.50:12040            # default 14025.5 kHz
//	go run ./cmd/psttest 192.168.1.50:12040 21074      # a specific kHz
//	go run ./cmd/psttest 192.168.1.50:12040 21074 3    # repeat each variant 3x
//
// Watch PstRotatorAz as it runs; when one variant makes it react, that's the
// format — tell me the variant number and I'll wire it into OpsLog.
package main

import (
	"fmt"
	"net"
	"os"
	"strconv"
	"time"
)

type variant struct {
	name string
	// build returns the datagram for a given frequency in kHz.
	build func(khz float64) string
}

func main() {
	if len(os.Args) < 2 {
		fmt.Println("usage: psttest <ip:port> [freqKHz] [repeat]")
		fmt.Println("example: psttest 192.168.1.50:12040 3525.5")
		os.Exit(2)
	}
	target := os.Args[1]
	khz := 3525.5
	if len(os.Args) >= 3 {
		if v, err := strconv.ParseFloat(os.Args[2], 64); err == nil {
			khz = v
		}
	}
	repeat := 1
	if len(os.Args) >= 4 {
		if v, err := strconv.Atoi(os.Args[3]); err == nil && v > 0 {
			repeat = v
		}
	}

	hz := int64(khz*1000 + 0.5)
	tensHz := hz / 10 // N1MM/DXLog <Freq> unit

	// Tag <PST><FREQUENCY> is confirmed. PstRotator strips the decimal point and
	// reads the digits, so pin down the exact unit: watch which one shows the real
	// frequency (3.5255 MHz), not 0.35255 / 0.003525 / 0.035255.
	variants := []variant{
		{"FREQUENCY = Hz integer  (expect 3.5255 MHz) ← prediction", func(k float64) string { return fmt.Sprintf("<PST><FREQUENCY>%d</FREQUENCY></PST>", hz) }},
		{"FREQUENCY = tens-of-Hz  (expect 0.35255 MHz)", func(k float64) string { return fmt.Sprintf("<PST><FREQUENCY>%d</FREQUENCY></PST>", tensHz) }},
		{"FREQUENCY = kHz integer (expect 0.003525 MHz)", func(k float64) string { return fmt.Sprintf("<PST><FREQUENCY>%d</FREQUENCY></PST>", int64(k+0.5)) }},
		{"FREQUENCY = kHz decimal (baseline: gave 0.035255 MHz)", func(k float64) string { return fmt.Sprintf("<PST><FREQUENCY>%.1f</FREQUENCY></PST>", k) }},
	}

	conn, err := net.Dial("udp", target)
	if err != nil {
		fmt.Printf("dial %s: %v\n", target, err)
		os.Exit(1)
	}
	defer conn.Close()

	fmt.Printf("Sending %d variants to %s at %.1f kHz (%d Hz, %d tens-of-Hz), %dx each.\n\n", len(variants), target, khz, hz, tensHz, repeat)
	for i, v := range variants {
		msg := v.build(khz)
		fmt.Printf("── Variant %d: %s\n", i+1, v.name)
		fmt.Printf("   payload: %s\n", msg)
		for r := 0; r < repeat; r++ {
			if _, err := conn.Write([]byte(msg)); err != nil {
				fmt.Printf("   write error: %v\n", err)
			}
			time.Sleep(300 * time.Millisecond)
		}
		fmt.Printf("   → sent. Watch PstRotatorAz for ~4s…\n\n")
		time.Sleep(4 * time.Second)
	}
	fmt.Println("Done. Which variant number made PstRotatorAz react?")
}
