// lang_fr.mbt — French number spelling (cardinal, year).
//
// French uses a vigesimal (base-20) system for 70-99:
//   70 = soixante-dix, 71 = soixante et onze, 80 = quatre-vingts,
//   90 = quatre-vingt-dix, 99 = quatre-vingt-dix-neuf.

///|
pub fn lang_fr() -> Lang {
  {
    variant: Fr,
    zero: "zéro",
    ones: [
      "zéro", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf",
    ],
    teens: [
      "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept",
      "dix-huit", "dix-neuf",
    ],
    tens: [
      "", "dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante-dix",
      "quatre-vingts", "quatre-vingt-dix",
    ],
    hundred: "cent",
    // scale words, index = group power (1 -> mille, 2 -> million, ...)
    thousands: [
      "", "mille", "million", "milliard", "billion", "billiard", "trillion", "trilliard",
      "quintillion", "quintilliard", "sextillion",
    ],
    negative: "moins",
    decimal: "virgule",
    comma_sep: false,
  }
}

///|
fn Lang::small_fr(self : Lang, x : Int) -> String {
  if x < 10 {
    self.ones[x]
  } else {
    self.teens[x - 10]
  }
}

///|
fn Lang::below100_fr(self : Lang, r : Int) -> String {
  if r < 10 {
    return self.ones[r]
  }
  if r < 20 {
    return self.teens[r - 10]
  }
  let d = r / 10
  let u = r % 10
  if d >= 2 && d <= 6 {
    if u == 0 {
      return self.tens[d]
    }
    if u == 1 {
      return self.tens[d] + " et un"
    }
    return self.tens[d] + "-" + self.ones[u]
  }
  if d == 7 {
    let rest = r - 70
    if rest == 0 {
      return "soixante-dix"
    }
    if rest == 1 {
      return "soixante et onze"
    }
    return "soixante-" + self.teens[rest]
  }
  // d == 8 or 9: quatre-vingt(s) + (0..19)
  let rest = r - 80
  if rest == 0 {
    return "quatre-vingts"
  }
  return "quatre-vingt-" + self.small_fr(rest)
}

///|
fn Lang::triple_fr(self : Lang, t : Int) -> String {
  if t == 0 {
    return ""
  }
  let h = t / 100
  let r = t % 100
  if h == 0 {
    return self.below100_fr(r)
  }
  if h == 1 {
    if r == 0 {
      return "cent"
    }
    return "cent " + self.below100_fr(r)
  }
  if r == 0 {
    return self.ones[h] + " cents"
  }
  return self.ones[h] + " cent " + self.below100_fr(r)
}

///|
fn Lang::cardinal_fr(self : Lang, n : BigInt) -> String {
  if n == BigInt::from_int(0) {
    return self.zero
  }
  if !self.supports(n) {
    return ""
  }
  let neg = n < BigInt::from_int(0)
  let n = if neg { -n } else { n }
  let groups = group3(n)
  let parts : Array[String] = []
  for i = 0; i < groups.length(); i = i + 1 {
    let (triple, power) = groups[i]
    let t = triple.to_int()
    if t == 0 {
      continue
    }
    let mut s = self.triple_fr(t)
    if power > 0 {
      if t == 1 && power == 1 {
        s = "mille"
      } else if t == 1 {
        s = "un " + self.thousands[power]
      } else {
        // Upstream drops the plural "s" of "cents"/"vingts" before "mille"
        // ("trois cent mille"), but keeps it before "millions" and up.
        if power == 1 && (ends_with(s, "cents") || ends_with(s, "vingts")) {
          s = drop_last_char(s)
        }
        s = s + " " + self.thousands[power]
        if triple > BigInt::from_int(1) && power >= 2 {
          s = s + "s"
        }
      }
    }
    parts.push(s)
  }
  let joined = join_parts(parts, " ")
  if neg {
    "moins " + joined
  } else {
    joined
  }
}

///|
/// French year reading (e.g. 2024 -> "vingt vingt-quatre").
pub fn year_fr(n : BigInt) -> String {
  if n < BigInt::from_int(1000) || n > BigInt::from_int(9999) {
    return lang_fr().cardinal_fr(n)
  }
  let neg = n < BigInt::from_int(0)
  let n = if neg { -n } else { n }
  if n % BigInt::from_int(1000) == BigInt::from_int(0) {
    return lang_fr().cardinal_fr(n)
  }
  let s = n.to_string()
  let first = BigInt::from_string(s[0:2].to_owned()).to_int()
  let second = BigInt::from_string(s[2:4].to_owned()).to_int()
  if second == 0 {
    return lang_fr().cardinal_fr(n)
  }
  let a = lang_fr().cardinal_fr(BigInt::from_int(first))
  let b = lang_fr().cardinal_fr(BigInt::from_int(second))
  if neg {
    "moins " + a + " " + b
  } else {
    a + " " + b
  }
}