package award

import "strings"

// Name normalisation for USCountyKey. It exists because the county a QSO
// carries and the county the USA-CA reference list carries come from different
// hands and rarely agree letter for letter:
//
//   - the reference is the FIPS list ("Doña Ana County", "Baltimore city");
//   - a callbook writes what the licensee typed;
//   - and OpsLog's own offline resolver reads GeoNames, which spells the
//     county-equivalents its own way ("Baltimore (city)", "Nome (CA)",
//     "City and County of San Francisco").
//
// Measured against a full FCC ULS import (1.56 M US callsigns), the shapes
// handled here account for ~7 300 stations whose county matched nothing at all
// — they showed as a new county for ever and counted for no award.
//
// Everything here is SPELLING. A county that genuinely no longer exists under
// that name is a different problem, handled by renamed below.

// foldAccents strips the diacritics that separate a FIPS name from the ASCII
// every log and callbook actually holds. Only the letters that occur in US
// place names are listed — this is not a general Unicode folder, and it must
// not become one: silently folding arbitrary marks would let two distinct
// references collapse onto one key.
var accents = strings.NewReplacer(
	"ñ", "n", "Ñ", "N",
	"á", "a", "Á", "A",
	"é", "e", "É", "E",
	"í", "i", "Í", "I",
	"ó", "o", "Ó", "O",
	"ú", "u", "Ú", "U",
	"ü", "u", "Ü", "U",
	"ç", "c", "Ç", "C",
)

func foldAccents(s string) string {
	// Fast path: US county names are ASCII with a single exception (Doña Ana),
	// so the common case must not pay for the replacer.
	for i := 0; i < len(s); i++ {
		if s[i] >= 0x80 {
			return accents.Replace(s)
		}
	}
	return s
}

// expandCountyEquivalent rewrites GeoNames' parenthetical and prefixed spellings
// of county-equivalents into the plain FIPS form, which the rest of USCountyKey
// then normalises as usual.
//
// Input is already upper-cased with periods and hyphens removed.
//
//	BALTIMORE (CITY)                 → BALTIMORE CITY   (FIPS "Baltimore city")
//	NOME (CA)                        → NOME CENSUS AREA (suffix stripped after)
//	CITY AND COUNTY OF SAN FRANCISCO → SAN FRANCISCO
//
// The truncated "(CITY" is not a typo here: GeoNames really does ship
// "Colonial Heights (city" with the closing parenthesis missing.
func expandCountyEquivalent(co string) string {
	switch {
	case strings.HasSuffix(co, " (CITY)"):
		co = strings.TrimSuffix(co, " (CITY)") + " CITY"
	case strings.HasSuffix(co, " (CITY"):
		co = strings.TrimSuffix(co, " (CITY") + " CITY"
	case strings.HasSuffix(co, " (CA)"):
		co = strings.TrimSuffix(co, " (CA)") + " CENSUS AREA"
	}
	// "City and County of X" and "City and Borough of X" are the same place as
	// FIPS's bare "X" (San Francisco, Denver, Honolulu, Juneau, Sitka). Note the
	// order: the longer prefixes must be tried before "CITY OF ".
	for _, p := range []string{
		"CITY AND COUNTY OF ",
		"CITY AND BOROUGH OF ",
		"MUNICIPALITY OF ",
		"BOROUGH OF ",
		"CITY OF ",
	} {
		if strings.HasPrefix(co, p) {
			return strings.TrimPrefix(co, p)
		}
	}
	return co
}

// renamed folds a county renamed or re-drawn since the CQ USA-CA list was
// published onto the name the award still counts. Keys and values are finished
// USCountyKey county parts (upper-case, no spaces), looked up as "ST/COUNTY".
//
// This deliberately does NOT track the FIPS list. USA-CA is a fixed target of
// ~3 100 counties; when a state renames one, the award does not reissue its
// list, so a QSO with the new name would otherwise match nothing and count for
// nothing. Folding it onto the old name is the only outcome that scores.
//
// Connecticut is absent on purpose. Its 2022 planning regions are not renamed
// counties: a region is drawn from towns belonging to several different
// counties, so there is no name that maps to another name. That one is resolved
// from the station's ZIP, in internal/uls.
var renamed = map[string]string{
	// Wade Hampton Census Area, AK → Kusilvak Census Area (2015).
	"AK/KUSILVAK": "WADEHAMPTON",
	// Shannon County, SD → Oglala Lakota County (2015).
	"SD/OGLALALAKOTA": "SHANNON",
	// Valdez-Cordova Census Area, AK was split in two (2019). Both halves fold
	// back to the parent the award still lists.
	"AK/CHUGACH":     "VALDEZCORDOVA",
	"AK/COPPERRIVER": "VALDEZCORDOVA",

	// Alaska's four "X City and Borough". The reference codes for these look
	// wrong and are not: the trailing " BOROUGH" is stripped as a county type,
	// leaving "JUNEAU CITY AND". Nothing else in the chain produces that shape
	// — a log that simply says "Juneau", and GeoNames' "City and Borough of
	// Juneau", both arrive here as "JUNEAU" and would match nothing. Rather
	// than re-key four published references, bend the bare name onto them.
	"AK/JUNEAU":   "JUNEAUCITYAND",
	"AK/SITKA":    "SITKACITYAND",
	"AK/WRANGELL": "WRANGELLCITYAND",
	"AK/YAKUTAT":  "YAKUTATCITYAND",
}
