// morphology-uga.el - Ugaritic morphology for the NLG engine.
//                     𐎀𐎎𐎗𐎚 — Ugaritic, the language of the city-state of Ugarit.
//
// Implements Ugaritic verb conjugation (G-stem, suffix and prefix conjugations),
// noun declension (three cases, gender, number, dual), and noun-phrase construction.
//
// Ugaritic is a Northwest Semitic language (ca. 1400–1200 BCE), written in a
// 30-character alphabetic cuneiform.  It is closely related to Biblical Hebrew
// and Phoenician.  We work in standard Latin transliteration:
//   ʼ = aleph (glottal stop)   ʻ = ʿayin   ḫ = het   ġ = ghayin
//   ṯ = thet  ẓ = emphatic z   š = shin     ṣ = tsade
//
// Language profile:
//   code=uga, name=Ugaritic, morph_type=semitic, word_order=VSO,
//   script=alphabetic cuneiform (transliterated), family=semitic/northwest-semitic
//
// Key grammatical facts:
//   - Semitic trilateral root system (nearly identical to Hebrew/Arabic)
//   - Grammatical gender: masculine / feminine
//   - Cases: nominative (-u), accusative (-a), genitive (-i)
//     (mirrors Akkadian but with shorter endings — no mimation in Ugaritic)
//   - Number: singular / plural / dual
//   - Dual: nom -āma, gen/acc -ēma
//   - Verb tenses:
//       qtl  (perfect, suffix conjugation)  — completed action
//       yqtl (imperfect, prefix conjugation) — ongoing / future action
//   - Verb stems: G, D, Š, N (this file: G-stem throughout)
//   - No separate definite article (unlike later Hebrew ha-)
//   - Copula: root kn (to be)
//
// Verb conjugation conventions:
//   person:  "first" | "second" | "third"
//   gender:  "m" | "f"
//   number:  "singular" | "plural"
//   tense:   "perfect" | "imperfect"
//
// Noun declension conventions:
//   gram_case: "nom" | "acc" | "gen"
//   number:    "singular" | "plural" | "dual"
//
// Verbs covered (G-stem root, transliterated):
//   "kn"   — to be  (copula)
//   "hlk"  — to go
//   "rʼy"  — to see
//   "ʼmr"  — to say
//
// Depends on: morphology.el (str_eq, str_len, str_slice, str_ends_with)

// ── String helpers ─────────────────────────────────────────────────────────────

fn uga_str_ends(s: String, suf: String) -> Bool {
    return str_ends_with(s, suf)
}

fn uga_str_len(s: String) -> Int {
    return str_len(s)
}

fn uga_str_drop_last(s: String, n: Int) -> String {
    let len: Int = str_len(s)
    if n >= len {
        return ""
    }
    return str_slice(s, 0, len - n)
}

// ── Slot index ─────────────────────────────────────────────────────────────────
//
// Maps person × number to a 0-based slot index.
// Gender is used separately for third-person disambiguation.
//
// Slot layout (6 primary cells, matching classic NW-Semitic paradigm):
//   0 = 1sg   (I)
//   1 = 2sg   (you sg — masc and fem conflate in many forms)
//   2 = 3sg m (he)
//   3 = 3sg f (she)
//   4 = 1pl   (we)
//   5 = 3pl   (they — masc default)

fn uga_slot(person: String, number: String) -> Int {
    if str_eq(person, "first") {
        if str_eq(number, "plural") { return 4 }
        return 0
    }
    if str_eq(person, "second") {
        return 1
    }
    // third
    if str_eq(number, "plural") { return 5 }
    return 2
}

// uga_slot_g: gender-sensitive slot for third-person singular.
fn uga_slot_g(person: String, gender: String, number: String) -> Int {
    let base: Int = uga_slot(person, number)
    if str_eq(person, "third") {
        if str_eq(number, "singular") {
            if str_eq(gender, "f") { return 3 }
        }
    }
    return base
}

// ── Copula: kn — to be ────────────────────────────────────────────────────────
//
// qtl  (perfect): kāna (3sg m), kānat (3sg f), kānu (3pl)
// yqtl (imperfect): yakūnu (3sg m), takūnu (3sg f / 2sg), ʼakūnu (1sg)
//
// The root kn is a weak verb (hollow: middle w/y).  The perfect stem is kāna-;
// the imperfect stem is -kūn-.

fn uga_kn_perfect(slot: Int) -> String {
    if slot == 0 { return "kāntu" }      // 1sg  (kān- + suffix -tu)
    if slot == 1 { return "kānta" }      // 2sg  (-ta suffix)
    if slot == 2 { return "kāna" }       // 3sg m (base)
    if slot == 3 { return "kānat" }      // 3sg f (-at suffix)
    if slot == 4 { return "kānnu" }      // 1pl  (-nu suffix)
    return "kānu"                         // 3pl  (-u suffix)
}

fn uga_kn_imperfect(slot: Int) -> String {
    if slot == 0 { return "ʼakūnu" }     // 1sg  (ʼa- prefix)
    if slot == 1 { return "takūnu" }     // 2sg  (ta- prefix)
    if slot == 2 { return "yakūnu" }     // 3sg m (ya- prefix)
    if slot == 3 { return "takūnu" }     // 3sg f (ta- prefix, same as 2sg)
    if slot == 4 { return "nakūnu" }     // 1pl  (na- prefix)
    return "yakūnuna"                     // 3pl  (ya- + -ūna energic suffix)
}

fn uga_is_copula(verb: String) -> Bool {
    if str_eq(verb, "kn")   { return true }
    if str_eq(verb, "kāna") { return true }
    if str_eq(verb, "be")   { return true }
    return false
}

fn uga_conjugate_copula(tense: String, slot: Int) -> String {
    if str_eq(tense, "perfect") { return uga_kn_perfect(slot) }
    return uga_kn_imperfect(slot)
}

// ── hlk — to go ───────────────────────────────────────────────────────────────
//
// Regular strong verb.  Perfect stem: halak-; imperfect stem: -hluk-.

fn uga_hlk_perfect(slot: Int) -> String {
    if slot == 0 { return "halaktu" }    // 1sg
    if slot == 1 { return "halakta" }    // 2sg
    if slot == 2 { return "halaka" }     // 3sg m
    if slot == 3 { return "halakat" }    // 3sg f
    if slot == 4 { return "halaknu" }    // 1pl
    return "halaku"                       // 3pl
}

fn uga_hlk_imperfect(slot: Int) -> String {
    if slot == 0 { return "ʼahluku" }    // 1sg
    if slot == 1 { return "tahluku" }    // 2sg
    if slot == 2 { return "yahluku" }    // 3sg m
    if slot == 3 { return "tahluku" }    // 3sg f
    if slot == 4 { return "nahluku" }    // 1pl
    return "yahlukuna"                    // 3pl
}

// ── rʼy — to see ──────────────────────────────────────────────────────────────
//
// Third-weak verb (final y).  Perfect: raʼaya (3sg m); imperfect: yarʼā (3sg m).

fn uga_ray_perfect(slot: Int) -> String {
    if slot == 0 { return "raʼaytu" }    // 1sg
    if slot == 1 { return "raʼayta" }    // 2sg
    if slot == 2 { return "raʼaya" }     // 3sg m
    if slot == 3 { return "raʼayat" }    // 3sg f
    if slot == 4 { return "raʼaynu" }    // 1pl
    return "raʼayu"                       // 3pl
}

fn uga_ray_imperfect(slot: Int) -> String {
    if slot == 0 { return "ʼarʼā" }      // 1sg
    if slot == 1 { return "tarʼā" }      // 2sg
    if slot == 2 { return "yarʼā" }      // 3sg m
    if slot == 3 { return "tarʼā" }      // 3sg f
    if slot == 4 { return "narʼā" }      // 1pl
    return "yarʼayna"                     // 3pl  (fem plural ending for final-weak)
}

// ── ʼmr — to say ──────────────────────────────────────────────────────────────
//
// Strong verb.  Perfect: ʼamara (3sg m); imperfect: yaʼmuru (3sg m).

fn uga_amr_perfect(slot: Int) -> String {
    if slot == 0 { return "ʼamartu" }    // 1sg
    if slot == 1 { return "ʼamarta" }    // 2sg
    if slot == 2 { return "ʼamara" }     // 3sg m
    if slot == 3 { return "ʼamarat" }    // 3sg f
    if slot == 4 { return "ʼamarnu" }    // 1pl
    return "ʼamaru"                       // 3pl
}

fn uga_amr_imperfect(slot: Int) -> String {
    if slot == 0 { return "ʼaʼmuru" }    // 1sg
    if slot == 1 { return "taʼmuru" }    // 2sg
    if slot == 2 { return "yaʼmuru" }    // 3sg m
    if slot == 3 { return "taʼmuru" }    // 3sg f
    if slot == 4 { return "naʼmuru" }    // 1pl
    return "yaʼmuruna"                    // 3pl
}

// ── Generic G-stem paradigm (regular strong verbs) ────────────────────────────
//
// For verbs not in the lookup table, apply the regular pattern.
// Caller supplies the 3sg perfect form (qtl) and 3sg imperfect (yqtl) form.
// We derive person forms by suffix/prefix substitution.

fn uga_generic_perfect(base3sg: String, slot: Int) -> String {
    // Perfect suffixes: 1sg -tu, 2sg -ta, 3sg m ∅, 3sg f -at, 1pl -nu, 3pl -u
    if slot == 0 { return base3sg + "tu" }
    if slot == 1 { return base3sg + "ta" }
    if slot == 2 { return base3sg }
    if slot == 3 { return base3sg + "at" }
    if slot == 4 { return base3sg + "nu" }
    return base3sg + "u"
}

fn uga_generic_imperfect(base3sg: String, slot: Int) -> String {
    // Strip leading ya- to get the core, re-prefix per person.
    // This is a heuristic for display purposes when the stem is unknown.
    if slot == 0 { return "ʼa" + base3sg }
    if slot == 1 { return "ta" + base3sg }
    if slot == 2 { return "ya" + base3sg }
    if slot == 3 { return "ta" + base3sg }
    if slot == 4 { return "na" + base3sg }
    return "ya" + base3sg + "una"
}

// ── Known-verb dispatcher ─────────────────────────────────────────────────────

fn uga_known_verb(verb: String, tense: String, slot: Int) -> String {
    // kn — to be
    if str_eq(verb, "kn") {
        return uga_conjugate_copula(tense, slot)
    }
    if str_eq(verb, "kāna") {
        return uga_conjugate_copula(tense, slot)
    }

    // hlk — to go
    if str_eq(verb, "hlk") {
        if str_eq(tense, "perfect") { return uga_hlk_perfect(slot) }
        return uga_hlk_imperfect(slot)
    }
    if str_eq(verb, "halaka") {
        if str_eq(tense, "perfect") { return uga_hlk_perfect(slot) }
        return uga_hlk_imperfect(slot)
    }

    // rʼy — to see
    if str_eq(verb, "rʼy") {
        if str_eq(tense, "perfect") { return uga_ray_perfect(slot) }
        return uga_ray_imperfect(slot)
    }
    if str_eq(verb, "raʼaya") {
        if str_eq(tense, "perfect") { return uga_ray_perfect(slot) }
        return uga_ray_imperfect(slot)
    }

    // ʼmr — to say
    if str_eq(verb, "ʼmr") {
        if str_eq(tense, "perfect") { return uga_amr_perfect(slot) }
        return uga_amr_imperfect(slot)
    }
    if str_eq(verb, "ʼamara") {
        if str_eq(tense, "perfect") { return uga_amr_perfect(slot) }
        return uga_amr_imperfect(slot)
    }

    return ""
}

// ── Main conjugation entry point ──────────────────────────────────────────────
//
// uga_conjugate: conjugate a Ugaritic verb (G-stem).
//
// verb:   root (2–3 consonants, e.g. "kn", "hlk") or 3sg perfect citation form
// tense:  "perfect" | "imperfect"
// person: "first" | "second" | "third"
// number: "singular" | "plural"
//
// Returns:
//   - Inflected form for known verbs
//   - verb unchanged as safe fallback for unknown verbs

fn uga_conjugate(verb: String, tense: String, person: String, number: String) -> String {
    let slot: Int = uga_slot(person, number)

    if uga_is_copula(verb) {
        return uga_conjugate_copula(tense, slot)
    }

    let known: String = uga_known_verb(verb, tense, slot)
    if !str_eq(known, "") {
        return known
    }

    return verb
}

// ── Noun declension ────────────────────────────────────────────────────────────
//
// uga_decline: decline a Ugaritic noun for gram_case and number.
//
// Ugaritic case endings (no mimation — unlike Akkadian):
//   Masculine singular:
//     Nominative: -u      (e.g. malku "king")
//     Accusative: -a      (e.g. malka)
//     Genitive:   -i      (e.g. malki)
//   Masculine plural:
//     Nominative: -ūma    (e.g. malkūma)
//     Genitive/Accusative: -īma  (e.g. malkīma)
//   Feminine singular (typically -atu base):
//     Nominative: -atu    (e.g. malaktu)
//     Accusative: -ata    (e.g. malakta)
//     Genitive:   -ati    (e.g. malakti)
//   Feminine plural:
//     Nominative: -ātu    (e.g. malakātu)
//     Genitive/Accusative: -āti
//   Dual:
//     Nominative: -āma    (e.g. malkāma)
//     Genitive/Accusative: -ēma
//
// Strategy: strip the known nominative ending to get the bare stem,
// then apply the requested ending.

fn uga_strip_nom(noun: String) -> String {
    // Strip masc sg -u
    if uga_str_ends(noun, "u") {
        let len: Int = uga_str_len(noun)
        if len > 1 {
            return uga_str_drop_last(noun, 1)
        }
    }
    // Strip fem sg -atu
    if uga_str_ends(noun, "atu") {
        return uga_str_drop_last(noun, 3)
    }
    return noun
}

fn uga_is_fem(noun: String) -> Bool {
    if uga_str_ends(noun, "atu") { return true }
    if uga_str_ends(noun, "ata") { return true }
    if uga_str_ends(noun, "ati") { return true }
    if uga_str_ends(noun, "ātu") { return true }
    if uga_str_ends(noun, "āti") { return true }
    return false
}

fn uga_decline(noun: String, gram_case: String, number: String) -> String {
    let fem: Bool = uga_is_fem(noun)
    let stem: String = uga_strip_nom(noun)

    if str_eq(number, "dual") {
        if str_eq(gram_case, "nom") { return stem + "āma" }
        return stem + "ēma"
    }

    if str_eq(number, "plural") {
        if fem {
            if str_eq(gram_case, "nom") { return stem + "ātu" }
            return stem + "āti"
        }
        // Masculine plural
        if str_eq(gram_case, "nom") { return stem + "ūma" }
        return stem + "īma"
    }

    // Singular
    if fem {
        if str_eq(gram_case, "nom") { return stem + "atu" }
        if str_eq(gram_case, "acc") { return stem + "ata" }
        if str_eq(gram_case, "gen") { return stem + "ati" }
        return stem + "atu"
    }
    // Masculine singular
    if str_eq(gram_case, "nom") { return stem + "u" }
    if str_eq(gram_case, "acc") { return stem + "a" }
    if str_eq(gram_case, "gen") { return stem + "i" }
    return stem + "u"
}

// ── Noun phrase ────────────────────────────────────────────────────────────────
//
// uga_noun_phrase: produce the surface noun phrase.
//
// Ugaritic has no separate definite article (unlike later Hebrew ha-).
// Determination is expressed through word order, the construct chain (genitive),
// and pronominal suffixes.  The definite parameter is accepted for interface
// uniformity but has no surface effect.
//
// noun:      base noun (nominative singular form, e.g. "malku")
// gram_case: "nom" | "acc" | "gen"
// number:    "singular" | "plural" | "dual"
// definite:  "true" | "false"  (no surface effect in Ugaritic)

fn uga_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String {
    return uga_decline(noun, gram_case, number)
}

// ── Canonical verb mapping ─────────────────────────────────────────────────────
//
// uga_map_canonical: map cross-lingual English canonical verb labels to
// Ugaritic G-stem roots or citation forms.

fn uga_map_canonical(verb: String) -> String {
    if str_eq(verb, "be")    { return "kn"   }
    if str_eq(verb, "go")    { return "hlk"  }
    if str_eq(verb, "see")   { return "rʼy"  }
    if str_eq(verb, "say")   { return "ʼmr"  }
    if str_eq(verb, "speak") { return "ʼmr"  }
    return verb
}
