package com.drivervault.phoneapp.car

import android.content.Context
import org.json.JSONObject
import java.io.IOException

/**
 * The car screens' text, read from the very same per-language files the phone
 * app reads — assets/i18n/{lang}.json, bundled into the APK under
 * flutter_assets/ — and looked up by the same dot-path keys. Nothing is retyped
 * here: a status badge on the head unit is the string lib/format.dart already
 * puts on the phone, in the language the account chose.
 *
 * The one thing t() in i18n.dart does that this does not is plurals: picking a
 * CLDR category is Intl's job, and no car screen needs one. A plural key comes
 * back as the key, which is what i18n.dart does with one it cannot render too.
 */
class CarStrings private constructor(
    private val active: JSONObject?,
    private val base: JSONObject?,
) {
    /** Translate [key], interpolating any `{name}` placeholders from [params]. */
    fun t(key: String, params: Map<String, Any?> = emptyMap()): String {
        val template = lookup(active, key) ?: lookup(base, key) ?: return key
        return interpolate(template, params)
    }

    private fun lookup(dict: JSONObject?, key: String): String? {
        var node: Any? = dict ?: return null
        for (part in key.split(".")) {
            node = (node as? JSONObject)?.opt(part) ?: return null
        }
        return node as? String
    }

    private fun interpolate(template: String, params: Map<String, Any?>): String =
        PLACEHOLDER.replace(template) { m ->
            params[m.groupValues[1]]?.toString() ?: m.value
        }

    companion object {
        private const val BASE = "en"
        private val PLACEHOLDER = Regex("""\{(\w+)}""")

        /** Loads the files for the account's language, falling back to English. */
        fun of(context: Context): CarStrings {
            val language = VaultStore.locale(context).substringBefore("-")
            val base = read(context, BASE)
            val active = if (language == BASE) null else read(context, language)
            return CarStrings(active, base)
        }

        private fun read(context: Context, language: String): JSONObject? = try {
            context.assets.open("flutter_assets/assets/i18n/$language.json").use {
                JSONObject(it.readBytes().toString(Charsets.UTF_8))
            }
        } catch (_: IOException) {
            // A language with no file of its own falls back to English, exactly
            // as it does on the phone.
            null
        }
    }
}
