// el-i18n — Localization for el-ui.
//
// Two-letter language tag + optional region: en, en-US, ar-EG, zh-Hant.
// Bundles map keys to either a plain string or a plural-form map.
// `t(key)` and `t_plural(key, count)` are the surface API.

// ── Locale ───────────────────────────────────────────────────────────────────

let DIR_LTR: String = "ltr"
let DIR_RTL: String = "rtl"

type Locale {
    language: String   // "en"
    region:   String   // "US" (may be empty)
    direction: String  // "ltr" | "rtl"
}

fn locale_new(language: String, region: String) -> Locale {
    let dir: String = "ltr"
    if str_eq(language, "ar")  { let dir = "rtl" }
    if str_eq(language, "he")  { let dir = "rtl" }
    if str_eq(language, "fa")  { let dir = "rtl" }
    if str_eq(language, "ur")  { let dir = "rtl" }
    { "language": language, "region": region, "direction": dir }
}

fn locale_en_us() -> Locale { locale_new("en", "US") }
fn locale_es_es() -> Locale { locale_new("es", "ES") }
fn locale_zh_cn() -> Locale { locale_new("zh", "CN") }
fn locale_ar_eg() -> Locale { locale_new("ar", "EG") }
fn locale_ja_jp() -> Locale { locale_new("ja", "JP") }

fn locale_tag(loc: Locale) -> String {
    if str_eq(loc.region, "") { return loc.language }
    loc.language + "-" + loc.region
}

fn is_rtl(loc: Locale) -> Bool {
    str_eq(loc.direction, "rtl")
}

// ── Plural forms (CLDR cardinal categories) ──────────────────────────────────
//
// Categories: zero, one, two, few, many, other.
// Most languages only use one + other; Arabic uses all six.

let PLURAL_ZERO:  String = "zero"
let PLURAL_ONE:   String = "one"
let PLURAL_TWO:   String = "two"
let PLURAL_FEW:   String = "few"
let PLURAL_MANY:  String = "many"
let PLURAL_OTHER: String = "other"

fn plural_form(loc: Locale, n: Int) -> String {
    if str_eq(loc.language, "ar") { return plural_form_arabic(n) }
    if str_eq(loc.language, "ru") { return plural_form_russian(n) }
    if str_eq(loc.language, "pl") { return plural_form_polish(n) }
    if str_eq(loc.language, "ja") { return PLURAL_OTHER }
    if str_eq(loc.language, "zh") { return PLURAL_OTHER }
    if str_eq(loc.language, "ko") { return PLURAL_OTHER }
    // Default English-like rule
    if n == 1 { return PLURAL_ONE }
    PLURAL_OTHER
}

fn plural_form_arabic(n: Int) -> String {
    if n == 0 { return PLURAL_ZERO }
    if n == 1 { return PLURAL_ONE }
    if n == 2 { return PLURAL_TWO }
    let mod100: Int = n - ((n / 100) * 100)
    if mod100 >= 3 {
        if mod100 <= 10 { return PLURAL_FEW }
    }
    if mod100 >= 11 {
        if mod100 <= 99 { return PLURAL_MANY }
    }
    PLURAL_OTHER
}

fn plural_form_russian(n: Int) -> String {
    let mod10:  Int = n - ((n / 10)  * 10)
    let mod100: Int = n - ((n / 100) * 100)
    if mod10 == 1 {
        if mod100 == 11 { return PLURAL_MANY }
        return PLURAL_ONE
    }
    if mod10 >= 2 {
        if mod10 <= 4 {
            if mod100 >= 12 {
                if mod100 <= 14 { return PLURAL_MANY }
            }
            return PLURAL_FEW
        }
    }
    PLURAL_MANY
}

fn plural_form_polish(n: Int) -> String {
    if n == 1 { return PLURAL_ONE }
    let mod10:  Int = n - ((n / 10)  * 10)
    let mod100: Int = n - ((n / 100) * 100)
    if mod10 >= 2 {
        if mod10 <= 4 {
            if mod100 >= 12 {
                if mod100 <= 14 { return PLURAL_MANY }
            }
            return PLURAL_FEW
        }
    }
    PLURAL_MANY
}

// ── Translation bundle ──────────────────────────────────────────────────────
//
// Stored as a JSON map: key -> value | { one: "...", other: "..." }
// `bundle_load_toml` parses a TOML file at load time (planned runtime fn).

fn bundle_new() -> String {
    "{}"
}

fn bundle_insert(bundle: String, key: String, value: String) -> String {
    json_set(bundle, key, "\"" + value + "\"")
}

fn bundle_insert_plural(bundle: String, key: String, plural_map_json: String) -> String {
    json_set(bundle, key, plural_map_json)
}

fn bundle_load_toml(path: String) -> String {
    let raw: String = fs_read(path)
    toml_to_json(raw)
}

// ── LocaleContext + t/t_plural ──────────────────────────────────────────────

type LocaleContext {
    locale: Locale
    bundle: String   // JSON
    fallback_bundle: String
}

fn locale_context_new(loc: Locale, bundle: String) -> LocaleContext {
    { "locale": loc, "bundle": bundle, "fallback_bundle": "{}" }
}

fn t(ctx: LocaleContext, key: String) -> String {
    let v: String = json_get(ctx.bundle, key)
    if str_eq(v, "") { let v = json_get(ctx.fallback_bundle, key) }
    if str_eq(v, "") { return key }
    v
}

fn t_plural(ctx: LocaleContext, key: String, n: Int) -> String {
    let entry: String = json_get(ctx.bundle, key)
    if str_eq(entry, "") { return key }
    let form: String = plural_form(ctx.locale, n)
    let template: String = json_get(entry, form)
    if str_eq(template, "") { let template = json_get(entry, PLURAL_OTHER) }
    if str_eq(template, "") { return key }
    str_replace(template, "{n}", int_to_str(n))
}

// ── Number / currency formatting ─────────────────────────────────────────────

fn format_integer(loc: Locale, n: Int) -> String {
    // Group thousands by the locale's separator. Stub: en uses ',', most EU uses '.'.
    let sep: String = ","
    if str_eq(loc.language, "es") { let sep = "." }
    if str_eq(loc.language, "de") { let sep = "." }
    if str_eq(loc.language, "fr") { let sep = " " }
    int_with_separator(n, sep)
}

fn format_number(loc: Locale, n: Int, fraction_digits: Int) -> String {
    let dec_sep: String = "."
    if str_eq(loc.language, "es") { let dec_sep = "," }
    if str_eq(loc.language, "de") { let dec_sep = "," }
    if str_eq(loc.language, "fr") { let dec_sep = "," }
    format_integer(loc, n) + dec_sep + repeat_str("0", fraction_digits)
}

fn format_percent(loc: Locale, value_x100: Int) -> String {
    let body: String = int_to_str(value_x100 / 100) + "."
        + int_to_str(value_x100 - ((value_x100 / 100) * 100))
    if str_eq(loc.language, "fr") { return body + " %" }
    body + "%"
}

fn format_currency(loc: Locale, amount_minor: Int, iso: String) -> String {
    // amount_minor is in the smallest unit (cents). Stub formatting only.
    let major: Int = amount_minor / 100
    let minor: Int = amount_minor - (major * 100)
    let body:  String = int_to_str(major) + "." + int_to_str(minor)
    if str_eq(iso, "USD") { return "$" + body }
    if str_eq(iso, "EUR") { return body + " €" }
    if str_eq(iso, "GBP") { return "£" + body }
    if str_eq(iso, "JPY") { return "¥" + int_to_str(amount_minor) }
    body + " " + iso
}

// ── Entry — smoke test ──────────────────────────────────────────────────────

let loc: Locale = locale_en_us()
let bundle: String = bundle_new()
let bundle = bundle_insert(bundle, "profile.follow", "Follow")
let ctx: LocaleContext = locale_context_new(loc, bundle)
println("[el-i18n] " + t(ctx, "profile.follow"))
