// Package contest holds a curated catalogue of the major amateur-radio contests
// with their official ADIF CONTEST_ID codes and a default exchange kind. It is
// deliberately a built-in static list (not an online fetch): the ADIF code is
// what must be written to each logged QSO's CONTEST_ID, and those codes don't
// change — bundling them means correct codes, offline, no fragile scraping.
//
// The Exchange field is only a UI hint for what a station typically sends; the
// operator can always override it (serial vs fixed, and the fixed kind) when
// activating the contest.
package contest

import "sort"

// Exchange kinds (UI prefill for the sent/received exchange).
const (
	ExSerial       = "serial"        // RST + running serial number
	ExCQZone       = "cq-zone"       // RST + CQ zone
	ExITUZone      = "itu-zone"      // RST + ITU zone
	ExState        = "state"         // RST + state / province
	ExDept         = "dept"          // RST + département (REF)
	ExGrid         = "grid"          // RST + Maidenhead grid
	ExName         = "name"          // name + state (NAQP-style)
	ExClassSection = "class-section" // Field Day: class + ARRL/RAC section
	ExRST          = "rst"           // RST only
)

// Def is one contest: its ADIF CONTEST_ID, a readable name, and the exchange a
// station typically sends.
type Def struct {
	Code     string `json:"code"`
	Name     string `json:"name"`
	Exchange string `json:"exchange"`
}

// catalogue is the built-in list. Codes are ADIF CONTEST_ID values.
var catalogue = []Def{
	{"CQ-WW-CW", "CQ WW DX Contest (CW)", ExCQZone},
	{"CQ-WW-SSB", "CQ WW DX Contest (SSB)", ExCQZone},
	{"CQ-WW-RTTY", "CQ WW DX RTTY Contest", ExCQZone},
	{"CQ-WPX-CW", "CQ WPX Contest (CW)", ExSerial},
	{"CQ-WPX-SSB", "CQ WPX Contest (SSB)", ExSerial},
	{"CQ-WPX-RTTY", "CQ WPX RTTY Contest", ExSerial},
	{"CQ-160-CW", "CQ 160-Meter Contest (CW)", ExState},
	{"CQ-160-SSB", "CQ 160-Meter Contest (SSB)", ExState},
	{"CQ-VHF", "CQ WW VHF Contest", ExGrid},
	{"ARRL-DX-CW", "ARRL International DX Contest (CW)", ExState},
	{"ARRL-DX-SSB", "ARRL International DX Contest (SSB)", ExState},
	{"ARRL-10", "ARRL 10-Meter Contest", ExState},
	{"ARRL-160", "ARRL 160-Meter Contest", ExState},
	{"ARRL-SS-CW", "ARRL Sweepstakes (CW)", ExSerial},
	{"ARRL-SS-SSB", "ARRL Sweepstakes (SSB)", ExSerial},
	{"ARRL-FIELD-DAY", "ARRL Field Day", ExClassSection},
	{"ARRL-RTTY", "ARRL RTTY Roundup", ExState},
	{"ARRL-DIGI", "ARRL Digital Contest", ExGrid},
	{"ARRL-VHF-JAN", "ARRL January VHF Contest", ExGrid},
	{"ARRL-VHF-JUN", "ARRL June VHF Contest", ExGrid},
	{"ARRL-VHF-SEP", "ARRL September VHF Contest", ExGrid},
	{"ARRL-UHF-AUG", "ARRL August UHF Contest", ExGrid},
	{"IARU-HF", "IARU HF World Championship", ExITUZone},
	{"WAE-DX-CW", "WAE DX Contest (CW)", ExSerial},
	{"WAE-DX-SSB", "WAE DX Contest (SSB)", ExSerial},
	{"WAE-DX-RTTY", "WAE DX Contest (RTTY)", ExSerial},
	{"NAQP-CW", "North American QSO Party (CW)", ExName},
	{"NAQP-SSB", "North American QSO Party (SSB)", ExName},
	{"NAQP-RTTY", "North American QSO Party (RTTY)", ExName},
	{"STEW-PERRY", "Stew Perry Topband Challenge", ExGrid},
	{"REF-CW", "REF Contest (CW)", ExDept},
	{"REF-SSB", "REF Contest (SSB)", ExDept},
	{"REF-160M", "REF 160m Contest", ExDept},
	{"OCEANIA-DX-CW", "Oceania DX Contest (CW)", ExSerial},
	{"OCEANIA-DX-SSB", "Oceania DX Contest (SSB)", ExSerial},
	{"HELVETIA", "Helvetia Contest", ExSerial},
	{"UKRAINIAN-DX", "Ukrainian DX Contest", ExSerial},
	{"WW-DIGI", "World Wide Digi DX Contest", ExGrid},
	{"EU-HF-C", "EU HF Championship", ExSerial},
	{"DARC-WAEDC", "WAEDC", ExSerial},
	// EME (Earth-Moon-Earth) contests — the exchange is a signal report (TMO /
	// RST), so there's no serial or fixed multiplier to prefill.
	{"ARRL-EME", "ARRL EME Contest", ExRST},
	{"DUBUS-REF-EME", "Dubus & REF EME Contest", ExRST},
	{"ARI-EME", "ARI EME Contest", ExRST},
}

// List returns the catalogue sorted by name (copy — callers must not mutate).
func List() []Def {
	out := make([]Def, len(catalogue))
	copy(out, catalogue)
	sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
	return out
}
