// morphology-sa.el - Sanskrit morphology for the NLG engine.
//
// Implements Sanskrit verb conjugation and noun declension using IAST
// transliteration as the primary form.  Designed as a companion to
// morphology.el and called by the engine when the language profile code
// is "sa".
//
// Language profile: code=sa, name=Sanskrit, morph_type=fusional,
//   word_order=SOV, question_strategy=intonation, script=devanagari,
//   family=indo-aryan.
//
// Verb conjugation covered:
//   Tenses:  present (laṭ), past (imperfect laṅ), future (lṛṭ)
//   Persons: first/second/third × singular/plural
//            (dual is treated as plural throughout — see sa_slot)
//   Classes: Class 1 (bhū-adi, stem + a + endings) as the regular path
//   Irregulars: as, bhū, gam, dṛś, vad, kṛ (the core NLG vocabulary)
//   Canonical map: "be" -> "as"
//
// Noun declension covered:
//   Cases:       nominative, accusative, instrumental, dative, ablative,
//                genitive, locative, vocative  (all 8 Sanskrit cases)
//   Stem types:  a-stem masculine (paradigm: deva),
//                ā-stem feminine  (paradigm: devī)
//   Numbers:     singular, plural (dual collapsed to plural)
//
// Sanskrit has no articles.  sa_noun_phrase returns the declined noun
// directly.
//
// Notes on IAST diacritics used throughout this file:
//   ā ī ū  — long vowels
//   ṛ      — vocalic r
//   ṃ      — anusvāra (nasalisation / homorganic nasal)
//   ḥ      — visarga (final breath)
//   ś ṣ    — palatal / retroflex sibilants
//   ṭ ḍ ṇ  — retroflex stops and nasal
//   ñ      — palatal nasal
//   Sandhi is intentionally suppressed — forms are returned in their
//   isolated (pausa) shapes so the NLG realizer can apply sandhi later.
//
// Depends on: morphology.el (str_eq, str_len, str_slice, str_ends_with)

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

import "morphology.el"
fn sa_str_ends(s: String, suf: String) -> Bool {
    return str_ends_with(s, suf)
}

fn sa_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)
}

// ── Person/number slot ─────────────────────────────────────────────────────────
//
// Maps person × number to a 0-based index into paradigm arrays.
//
//   0 = 1st singular   (uttama eka)
//   1 = 2nd singular   (madhyama eka)
//   2 = 3rd singular   (prathama eka)
//   3 = 1st plural     (uttama bahu)
//   4 = 2nd plural     (madhyama bahu)
//   5 = 3rd plural     (prathama bahu)
//
// Sanskrit has a dual number but for NLG simplicity the dual is collapsed:
// "dual" inputs return the same slot as "plural".  Forms in this file
// therefore carry plural endings even when the dual was requested.

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

// ── Canonical verb mapping ─────────────────────────────────────────────────────
//
// Semantic-layer canonical English labels are mapped to IAST dictionary
// entries before conjugation.  The dictionary entry is then looked up in
// the irregular table; unknown entries fall through to the Class-1 path.

fn sa_map_canonical(verb: String) -> String {
    if str_eq(verb, "be")     { return "as" }
    if str_eq(verb, "become") { return "bhu" }
    if str_eq(verb, "go")     { return "gam" }
    if str_eq(verb, "see")    { return "drs" }
    if str_eq(verb, "speak")  { return "vad" }
    if str_eq(verb, "say")    { return "vad" }
    if str_eq(verb, "do")     { return "kr" }
    if str_eq(verb, "make")   { return "kr" }
    return verb
}

// ── Irregular verb: as (to be) ────────────────────────────────────────────────
//
// Present (laṭ) parasmaipada:
//   1sg asmi  2sg asi    3sg asti
//   1pl smaḥ  2pl stha   3pl santi
//
// Imperfect (laṅ) parasmaipada:
//   1sg āsam  2sg āsīḥ   3sg āsīt
//   1pl āsma  2pl āsta   3pl āsan

fn sa_as_present(slot: Int) -> String {
    if slot == 0 { return "asmi" }
    if slot == 1 { return "asi" }
    if slot == 2 { return "asti" }
    if slot == 3 { return "smaḥ" }
    if slot == 4 { return "stha" }
    return "santi"
}

fn sa_as_past(slot: Int) -> String {
    if slot == 0 { return "āsam" }
    if slot == 1 { return "āsīḥ" }
    if slot == 2 { return "āsīt" }
    if slot == 3 { return "āsma" }
    if slot == 4 { return "āsta" }
    return "āsan"
}

// Future (lṛṭ) of as: bhaviṣyāmi series (uses bhū as suppletive stem)
fn sa_as_future(slot: Int) -> String {
    if slot == 0 { return "bhaviṣyāmi" }
    if slot == 1 { return "bhaviṣyasi" }
    if slot == 2 { return "bhaviṣyati" }
    if slot == 3 { return "bhaviṣyāmaḥ" }
    if slot == 4 { return "bhaviṣyatha" }
    return "bhaviṣyanti"
}

// ── Irregular verb: bhū (to be, to become) ────────────────────────────────────
//
// Class 1; present stem bho → bhava (guṇa of u before -a-).
//
// Present (laṭ):
//   1sg bhavāmi  2sg bhavasi  3sg bhavati
//   1pl bhavāmaḥ 2pl bhavatha 3pl bhavanti
//
// Imperfect (laṅ):
//   1sg abhavam  2sg abhavaḥ  3sg abhavat
//   1pl abhavāma 2pl abhavata 3pl abhavan
//
// Future (lṛṭ): regular from bhaviṣya-

fn sa_bhu_present(slot: Int) -> String {
    if slot == 0 { return "bhavāmi" }
    if slot == 1 { return "bhavasi" }
    if slot == 2 { return "bhavati" }
    if slot == 3 { return "bhavāmaḥ" }
    if slot == 4 { return "bhavatha" }
    return "bhavanti"
}

fn sa_bhu_past(slot: Int) -> String {
    if slot == 0 { return "abhavam" }
    if slot == 1 { return "abhavaḥ" }
    if slot == 2 { return "abhavat" }
    if slot == 3 { return "abhavāma" }
    if slot == 4 { return "abhavata" }
    return "abhavan"
}

fn sa_bhu_future(slot: Int) -> String {
    if slot == 0 { return "bhaviṣyāmi" }
    if slot == 1 { return "bhaviṣyasi" }
    if slot == 2 { return "bhaviṣyati" }
    if slot == 3 { return "bhaviṣyāmaḥ" }
    if slot == 4 { return "bhaviṣyatha" }
    return "bhaviṣyanti"
}

// ── Irregular verb: gam (to go) ───────────────────────────────────────────────
//
// Historically Class 1 with the present stem gaccha- (inserted -ccha-).
//
// Present (laṭ):
//   gacchāmi  gacchasi  gacchati
//   gacchāmaḥ gacchatha gacchanti
//
// Imperfect (laṅ): augmented agaccha-
//
// Future: gamiṣyati series

fn sa_gam_present(slot: Int) -> String {
    if slot == 0 { return "gacchāmi" }
    if slot == 1 { return "gacchasi" }
    if slot == 2 { return "gacchati" }
    if slot == 3 { return "gacchāmaḥ" }
    if slot == 4 { return "gacchatha" }
    return "gacchanti"
}

fn sa_gam_past(slot: Int) -> String {
    if slot == 0 { return "agaccham" }
    if slot == 1 { return "agacchaḥ" }
    if slot == 2 { return "agacchat" }
    if slot == 3 { return "agacchāma" }
    if slot == 4 { return "agacchata" }
    return "agacchan"
}

fn sa_gam_future(slot: Int) -> String {
    if slot == 0 { return "gamiṣyāmi" }
    if slot == 1 { return "gamiṣyasi" }
    if slot == 2 { return "gamiṣyati" }
    if slot == 3 { return "gamiṣyāmaḥ" }
    if slot == 4 { return "gamiṣyatha" }
    return "gamiṣyanti"
}

// ── Irregular verb: dṛś (to see) ─────────────────────────────────────────────
//
// Suppletive present stem paśya- (Class 4 / ātmanepada suppletive).
// Used in the active (parasmaipada) sense throughout for NLG simplicity.
//
// Present: paśyāmi paśyasi paśyati paśyāmaḥ paśyatha paśyanti
// Imperfect: apaśyam series
// Future: drakṣyati series

fn sa_drs_present(slot: Int) -> String {
    if slot == 0 { return "paśyāmi" }
    if slot == 1 { return "paśyasi" }
    if slot == 2 { return "paśyati" }
    if slot == 3 { return "paśyāmaḥ" }
    if slot == 4 { return "paśyatha" }
    return "paśyanti"
}

fn sa_drs_past(slot: Int) -> String {
    if slot == 0 { return "apaśyam" }
    if slot == 1 { return "apaśyaḥ" }
    if slot == 2 { return "apaśyat" }
    if slot == 3 { return "apaśyāma" }
    if slot == 4 { return "apaśyata" }
    return "apaśyan"
}

fn sa_drs_future(slot: Int) -> String {
    if slot == 0 { return "drakṣyāmi" }
    if slot == 1 { return "drakṣyasi" }
    if slot == 2 { return "drakṣyati" }
    if slot == 3 { return "drakṣyāmaḥ" }
    if slot == 4 { return "drakṣyatha" }
    return "drakṣyanti"
}

// ── Irregular verb: vad (to speak, to say) ────────────────────────────────────
//
// Class 1; present stem vada-.
//
// Present: vadāmi vadasi vadati vadāmaḥ vadatha vadanti
// Imperfect: avadam series
// Future: vadiṣyati series

fn sa_vad_present(slot: Int) -> String {
    if slot == 0 { return "vadāmi" }
    if slot == 1 { return "vadasi" }
    if slot == 2 { return "vadati" }
    if slot == 3 { return "vadāmaḥ" }
    if slot == 4 { return "vadatha" }
    return "vadanti"
}

fn sa_vad_past(slot: Int) -> String {
    if slot == 0 { return "avadam" }
    if slot == 1 { return "avadaḥ" }
    if slot == 2 { return "avadat" }
    if slot == 3 { return "avadāma" }
    if slot == 4 { return "avadata" }
    return "avadan"
}

fn sa_vad_future(slot: Int) -> String {
    if slot == 0 { return "vadiṣyāmi" }
    if slot == 1 { return "vadiṣyasi" }
    if slot == 2 { return "vadiṣyati" }
    if slot == 3 { return "vadiṣyāmaḥ" }
    if slot == 4 { return "vadiṣyatha" }
    return "vadiṣyanti"
}

// ── Irregular verb: kṛ (to do, to make) ──────────────────────────────────────
//
// Class 8 (tanādi); highly irregular.  Present stem karo- (sg) / kuru- (pl).
//
// Present:
//   1sg karomi   2sg karoṣi   3sg karoti
//   1pl kurmaḥ   2pl kurutha  3pl kurvanti
//
// Imperfect: akaro- / akuru-
// Future: kariṣyati series

fn sa_kr_present(slot: Int) -> String {
    if slot == 0 { return "karomi" }
    if slot == 1 { return "karoṣi" }
    if slot == 2 { return "karoti" }
    if slot == 3 { return "kurmaḥ" }
    if slot == 4 { return "kurutha" }
    return "kurvanti"
}

fn sa_kr_past(slot: Int) -> String {
    if slot == 0 { return "akaravam" }
    if slot == 1 { return "akarodaḥ" }
    if slot == 2 { return "akarot" }
    if slot == 3 { return "akurma" }
    if slot == 4 { return "akuruta" }
    return "akurvan"
}

fn sa_kr_future(slot: Int) -> String {
    if slot == 0 { return "kariṣyāmi" }
    if slot == 1 { return "kariṣyasi" }
    if slot == 2 { return "kariṣyati" }
    if slot == 3 { return "kariṣyāmaḥ" }
    if slot == 4 { return "kariṣyatha" }
    return "kariṣyanti"
}

// ── Class-1 regular conjugation (bhū-adi) ─────────────────────────────────────
//
// The thematic class: root → guṇa-strengthened root → + a + personal ending.
// Present endings (parasmaipada):
//   1sg -āmi   2sg -asi   3sg -ati
//   1pl -āmaḥ  2pl -atha  3pl -anti
//
// Imperfect (laṅ) = augment a- + stem + imperfect endings:
//   1sg -am   2sg -aḥ   3sg -at
//   1pl -āma  2pl -ata  3pl -an
//
// Future (lṛṭ) = stem + iṣya + present personal endings
//
// The caller supplies the present-tense verbal stem (e.g. "bodha" for
// "to know/wake").  We do not derive stems automatically from roots for
// arbitrary input — only the known irregular verbs above have root→stem
// derivation.  Unknown verbs are conjugated as if their input IS the stem.

fn sa_class1_present_ending(slot: Int) -> String {
    if slot == 0 { return "āmi" }
    if slot == 1 { return "asi" }
    if slot == 2 { return "ati" }
    if slot == 3 { return "āmaḥ" }
    if slot == 4 { return "atha" }
    return "anti"
}

fn sa_class1_past_ending(slot: Int) -> String {
    if slot == 0 { return "am" }
    if slot == 1 { return "aḥ" }
    if slot == 2 { return "at" }
    if slot == 3 { return "āma" }
    if slot == 4 { return "ata" }
    return "an"
}

fn sa_class1_future_ending(slot: Int) -> String {
    if slot == 0 { return "iṣyāmi" }
    if slot == 1 { return "iṣyasi" }
    if slot == 2 { return "iṣyati" }
    if slot == 3 { return "iṣyāmaḥ" }
    if slot == 4 { return "iṣyatha" }
    return "iṣyanti"
}

fn sa_class1_conjugate(stem: String, tense: String, slot: Int) -> String {
    if str_eq(tense, "present") {
        return stem + sa_class1_present_ending(slot)
    }
    if str_eq(tense, "past") {
        return "a" + stem + sa_class1_past_ending(slot)
    }
    if str_eq(tense, "future") {
        return stem + sa_class1_future_ending(slot)
    }
    return stem
}

// ── sa_conjugate: main conjugation entry point ────────────────────────────────
//
// verb:   IAST form (e.g. "gam", "as") or English canonical ("be", "go")
// tense:  "present" | "past" | "future"
// person: "first" | "second" | "third"
// number: "singular" | "plural" (or "dual" — treated as plural)
//
// Returns the inflected form in IAST.  Falls back to the verb stem for any
// unknown input rather than crashing.

fn sa_conjugate(verb: String, tense: String, person: String, number: String) -> String {
    let v: String = sa_map_canonical(verb)
    let slot: Int = sa_slot(person, number)

    // ── Irregular: as (to be) ─────────────────────────────────────────────────
    if str_eq(v, "as") {
        if str_eq(tense, "present") { return sa_as_present(slot) }
        if str_eq(tense, "past")    { return sa_as_past(slot) }
        if str_eq(tense, "future")  { return sa_as_future(slot) }
        return v
    }

    // ── Irregular: bhū (to be/become) ────────────────────────────────────────
    if str_eq(v, "bhu") {
        if str_eq(tense, "present") { return sa_bhu_present(slot) }
        if str_eq(tense, "past")    { return sa_bhu_past(slot) }
        if str_eq(tense, "future")  { return sa_bhu_future(slot) }
        return v
    }

    // ── Irregular: gam (to go) ────────────────────────────────────────────────
    if str_eq(v, "gam") {
        if str_eq(tense, "present") { return sa_gam_present(slot) }
        if str_eq(tense, "past")    { return sa_gam_past(slot) }
        if str_eq(tense, "future")  { return sa_gam_future(slot) }
        return v
    }

    // ── Irregular: dṛś / drs (to see) ────────────────────────────────────────
    if str_eq(v, "drs") {
        if str_eq(tense, "present") { return sa_drs_present(slot) }
        if str_eq(tense, "past")    { return sa_drs_past(slot) }
        if str_eq(tense, "future")  { return sa_drs_future(slot) }
        return v
    }

    // ── Irregular: vad (to speak/say) ────────────────────────────────────────
    if str_eq(v, "vad") {
        if str_eq(tense, "present") { return sa_vad_present(slot) }
        if str_eq(tense, "past")    { return sa_vad_past(slot) }
        if str_eq(tense, "future")  { return sa_vad_future(slot) }
        return v
    }

    // ── Irregular: kṛ / kr (to do/make) ──────────────────────────────────────
    if str_eq(v, "kr") {
        if str_eq(tense, "present") { return sa_kr_present(slot) }
        if str_eq(tense, "past")    { return sa_kr_past(slot) }
        if str_eq(tense, "future")  { return sa_kr_future(slot) }
        return v
    }

    // ── Regular Class-1 fallback ──────────────────────────────────────────────
    // Treat the supplied string as a present-tense verbal stem and apply the
    // standard thematic endings.  This handles any verb the caller passes in
    // the form "<stem>" without a recognised root tag.
    return sa_class1_conjugate(v, tense, slot)
}

// ── a-stem masculine paradigm (deva) ──────────────────────────────────────────
//
// Stems of the deva- type are the most numerous Sanskrit noun class.
// All eight cases × singular and plural are encoded below.
//
// Singular:
//   nom  deva-ḥ   → "devaḥ"     (visarga in citation; use bare form here)
//   acc  deva-m   → "devam"
//   ins  deva-na  → "devena"    (guṇa: a+n→ena)
//   dat  deva-āya → "devāya"
//   abl  deva-āt  → "devāt"
//   gen  deva-sya → "devasya"
//   loc  deva-e   → "deve"
//   voc  deva     → "deva"      (bare stem)
//
// Plural:
//   nom  deva-āḥ  → "devāḥ"
//   acc  deva-ān  → "devān"
//   ins  deva-aiḥ → "devaiḥ"
//   dat  deva-bhyaḥ → "devebhyaḥ"  (with connecting -e-)
//   abl  deva-bhyaḥ → "devebhyaḥ"  (dat=abl in plural for a-stems)
//   gen  deva-ānām → "devānām"
//   loc  deva-eṣu  → "deveṣu"
//   voc  deva-āḥ  → "devāḥ"

fn sa_decline_a_stem_sg(stem: String, gram_case: String) -> String {
    if str_eq(gram_case, "nominative")   { return stem + "ḥ" }
    if str_eq(gram_case, "accusative")   { return stem + "m" }
    if str_eq(gram_case, "instrumental") { return stem + "ena" }
    if str_eq(gram_case, "dative")       { return stem + "āya" }
    if str_eq(gram_case, "ablative")     { return stem + "āt" }
    if str_eq(gram_case, "genitive")     { return stem + "sya" }
    if str_eq(gram_case, "locative")     { return stem + "e" }
    if str_eq(gram_case, "vocative")     { return stem }
    return stem
}

fn sa_decline_a_stem_pl(stem: String, gram_case: String) -> String {
    if str_eq(gram_case, "nominative")   { return stem + "āḥ" }
    if str_eq(gram_case, "accusative")   { return stem + "ān" }
    if str_eq(gram_case, "instrumental") { return stem + "aiḥ" }
    if str_eq(gram_case, "dative")       { return stem + "ebhyaḥ" }
    if str_eq(gram_case, "ablative")     { return stem + "ebhyaḥ" }
    if str_eq(gram_case, "genitive")     { return stem + "ānām" }
    if str_eq(gram_case, "locative")     { return stem + "eṣu" }
    if str_eq(gram_case, "vocative")     { return stem + "āḥ" }
    return stem + "āḥ"
}

// ── ā-stem feminine paradigm (devī / nārī type) ───────────────────────────────
//
// ā-stems are the primary feminine class.  Paradigm for nārī (woman):
//
// Singular:
//   nom  nārī     acc  nārīm    ins  nāryā
//   dat  nāryai   abl  nāryāḥ  gen  nāryāḥ
//   loc  nāryām   voc  nāri
//
// Plural:
//   nom  nāryaḥ   acc  nārīḥ   ins  nārībhiḥ
//   dat  nārībhyaḥ abl nārībhyaḥ gen nārīṇām
//   loc  nārīṣu   voc  nāryaḥ
//
// For input the caller passes the nominative singular form (e.g. "nārī").
// We strip the final ī to obtain the stem for oblique formation.

fn sa_decline_aa_stem_sg(stem: String, gram_case: String) -> String {
    if str_eq(gram_case, "nominative")   { return stem + "ī" }
    if str_eq(gram_case, "accusative")   { return stem + "īm" }
    if str_eq(gram_case, "instrumental") { return stem + "yā" }
    if str_eq(gram_case, "dative")       { return stem + "yai" }
    if str_eq(gram_case, "ablative")     { return stem + "yāḥ" }
    if str_eq(gram_case, "genitive")     { return stem + "yāḥ" }
    if str_eq(gram_case, "locative")     { return stem + "yām" }
    if str_eq(gram_case, "vocative")     { return stem + "i" }
    return stem + "ī"
}

fn sa_decline_aa_stem_pl(stem: String, gram_case: String) -> String {
    if str_eq(gram_case, "nominative")   { return stem + "yaḥ" }
    if str_eq(gram_case, "accusative")   { return stem + "īḥ" }
    if str_eq(gram_case, "instrumental") { return stem + "ībhiḥ" }
    if str_eq(gram_case, "dative")       { return stem + "ībhyaḥ" }
    if str_eq(gram_case, "ablative")     { return stem + "ībhyaḥ" }
    if str_eq(gram_case, "genitive")     { return stem + "īṇām" }
    if str_eq(gram_case, "locative")     { return stem + "īṣu" }
    if str_eq(gram_case, "vocative")     { return stem + "yaḥ" }
    return stem + "yaḥ"
}

// ── Stem-type detection ────────────────────────────────────────────────────────
//
// Infers the stem class from the nominative singular form supplied by the
// caller.  Sanskrit stems are conventionally cited in their nom-sg form.
//
// Heuristics (sufficient for the NLG working vocabulary):
//   ends in ā  -> ā-stem feminine
//   ends in ī  -> ā-stem feminine (long ī subtype)
//   ends in aḥ -> a-stem masculine (visarga ending from -as)
//   ends in a  -> treat as a-stem masculine (bare stem supplied)
//   otherwise  -> return base form as-is (unknown/consonant stem fallback)

fn sa_stem_type(noun: String) -> String {
    if sa_str_ends(noun, "ā")  { return "aa" }
    if sa_str_ends(noun, "ī")  { return "aa" }
    if sa_str_ends(noun, "aḥ") { return "a" }
    if sa_str_ends(noun, "a")  { return "a" }
    return "unknown"
}

// sa_extract_stem: strip the nominative-singular suffix to get the bare stem.
//
// a-stem  "deva"  -> "dev" (if ends in bare -a; strip final char)
//          "devaḥ" -> "dev" (strip -aḥ = 2 Unicode code-points … but
//                             since ḥ is multi-byte we treat "aḥ" as suffix)
// ā-stem  "nārī"  -> "nār" (strip -ī)
//          "nārā"  -> "nār" (strip -ā)
//
// Because IAST diacritics are multi-byte UTF-8 the raw byte lengths do not
// equal character counts.  The engine's str_len / str_slice operate on bytes.
// Rather than counting UTF-8 bytes for each diacritic here we take a simpler
// path: we look for a known suffix and drop a fixed number of characters.
// For the characters used:
//   ā  = 2 bytes (U+0101)
//   ī  = 2 bytes (U+012B)
//   ḥ  = 3 bytes (U+1E25)
// So "aḥ" = 1 + 3 = 4 bytes; bare "a" = 1 byte; "ā" = 2 bytes; "ī" = 2 bytes.
//
// The function uses str_ends_with for detection, then str_slice to strip.

fn sa_extract_stem(noun: String, stype: String) -> String {
    let n: Int = str_len(noun)
    if str_eq(stype, "a") {
        // Check whether it ends in "aḥ" (visarga form): 4 bytes to strip
        if sa_str_ends(noun, "aḥ") {
            return str_slice(noun, 0, n - 4)
        }
        // Otherwise bare -a: 1 byte
        return str_slice(noun, 0, n - 1)
    }
    if str_eq(stype, "aa") {
        // ī or ā: both 2 bytes
        return str_slice(noun, 0, n - 2)
    }
    return noun
}

// ── sa_decline: main declension entry point ───────────────────────────────────
//
// noun:      nominative singular IAST form (e.g. "deva", "devaḥ", "nārī")
// gram_case: "nominative" | "accusative" | "instrumental" | "dative" |
//            "ablative" | "genitive" | "locative" | "vocative"
// number:    "singular" | "plural" (dual → plural)
//
// Returns the inflected form.  Unknown stems return the noun unchanged.

fn sa_decline(noun: String, gram_case: String, number: String) -> String {
    let stype: String = sa_stem_type(noun)

    if str_eq(stype, "a") {
        let stem: String = sa_extract_stem(noun, "a")
        if str_eq(number, "singular") { return sa_decline_a_stem_sg(stem, gram_case) }
        return sa_decline_a_stem_pl(stem, gram_case)
    }

    if str_eq(stype, "aa") {
        let stem: String = sa_extract_stem(noun, "aa")
        if str_eq(number, "singular") { return sa_decline_aa_stem_sg(stem, gram_case) }
        return sa_decline_aa_stem_pl(stem, gram_case)
    }

    // Unknown stem class: return noun unchanged rather than producing garbage
    return noun
}

// ── sa_noun_phrase: noun phrase builder ───────────────────────────────────────
//
// Sanskrit has no articles — neither definite nor indefinite.  The definite
// parameter is accepted for interface compatibility with other language modules
// but has no effect on the output.
//
// Sanskrit expresses definiteness and referential status through word order,
// demonstratives (etad / tad), and discourse context — none of which is the
// responsibility of the morphology module.
//
// noun:      nominative singular IAST form
// gram_case: "nominative" | "accusative" | "instrumental" | "dative" |
//            "ablative" | "genitive" | "locative" | "vocative"
// number:    "singular" | "plural"
// definite:  ignored

fn sa_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String {
    return sa_decline(noun, gram_case, number)
}
