// main.el — el-plugin-host
//
// Plugin lifecycle manager for el-ide. Pure-El port of the el-plugin-host
// Rust crate.
//
// Plugins are stored in process-global state via state_get / state_set.
// Each plugin lives under a key prefix `plugin/<name>/<field>`. The
// canonical list of plugin names is maintained at `plugins/index` as a
// comma-separated string (we don't have list serialisation in state yet).
//
// Public API:
//   plugin_init()                          — seed first-party plugins (idempotent)
//   plugin_list_json()       -> String     — JSON array of all plugins
//   plugin_get_json(name)    -> String     — JSON object or "null"
//   plugin_install(name)     -> String     — JSON { ok | error }
//   plugin_remove(name)      -> String
//   plugin_enable(name)      -> String
//   plugin_disable(name)     -> String

// ── State helpers (string K/V) ───────────────────────────────────────────────

fn pkey(name: String, field: String) -> String {
    "plugin/" + name + "/" + field
}

fn put_str(name: String, field: String, value: String) -> Void {
    state_set(pkey(name, field), value)
}

fn put_bool(name: String, field: String, value: Bool) -> Void {
    if value { state_set(pkey(name, field), "true") }
    if !value { state_set(pkey(name, field), "false") }
}

fn get_str(name: String, field: String) -> String {
    state_get(pkey(name, field))
}

fn get_bool(name: String, field: String) -> Bool {
    str_eq(state_get(pkey(name, field)), "true")
}

// Plugin index: comma-separated list of names at "plugins/index".
fn index_list() -> [String] {
    let raw: String = state_get("plugins/index")
    if str_eq(raw, "") { return native_list_empty() }
    str_split(raw, ",")
}

fn index_set(names: [String]) -> Void {
    state_set("plugins/index", list_join(names, ","))
}

fn index_contains(name: String) -> Bool {
    let names: [String] = index_list()
    let n: Int = native_list_len(names)
    let i: Int = 0
    while i < n {
        if str_eq(native_list_get(names, i), name) { return true }
        let i = i + 1
    }
    false
}

fn index_add(name: String) -> Void {
    if !index_contains(name) {
        let names: [String] = index_list()
        let names = native_list_append(names, name)
        index_set(names)
    }
}

// ── Initialisation ───────────────────────────────────────────────────────────

fn register_plugin(name: String, version: String, description: String,
                   installed: Bool, enabled: Bool, hooks: String,
                   first_party: Bool) -> Void {
    put_str(name, "name", name)
    put_str(name, "version", version)
    put_str(name, "description", description)
    put_bool(name, "installed", installed)
    put_bool(name, "enabled", enabled)
    put_str(name, "hooks", hooks)
    put_bool(name, "first_party", first_party)
    index_add(name)
}

fn plugin_init() -> Void {
    if str_eq(state_get("plugins/initialised"), "true") {
        return
    }
    register_plugin("el-theme-dark",  "1.0.0", "Dark theme — the default Engram IDE theme.",                                   true,  true,  "",                          true)
    register_plugin("el-theme-light", "1.0.0", "Light theme for high-ambient-light environments.",                              false, false, "",                          true)
    register_plugin("el-fmt",         "0.1.0", "Code formatter — auto-formats .el files on save.",                              true,  true,  "on_save",                   true)
    register_plugin("el-doc",         "0.1.0", "Documentation generator — produces HTML docs from type definitions.",          false, false, "custom_tool",               true)
    register_plugin("el-test",        "0.1.0", "Test runner with inline results displayed in the editor gutter.",              false, false, "on_build_complete,custom_panel", true)
    state_set("plugins/initialised", "true")
}

// ── Serialisation ────────────────────────────────────────────────────────────

fn json_escape_str(s: String) -> String {
    let chars: [String] = native_string_chars(s)
    let n: Int = native_list_len(chars)
    let out: String = ""
    let i: Int = 0
    while i < n {
        let ch: String = native_list_get(chars, i)
        if ch == "\"" { let out = out + "\\\"" }
        else { if ch == "\\" { let out = out + "\\\\" }
        else { if ch == "\n" { let out = out + "\\n" }
        else { let out = out + ch } } }
        let i = i + 1
    }
    out
}

fn quote_json(s: String) -> String {
    "\"" + json_escape_str(s) + "\""
}

fn hooks_to_json(hooks_csv: String) -> String {
    if str_eq(hooks_csv, "") { return "[]" }
    let xs: [String] = str_split(hooks_csv, ",")
    let n: Int = native_list_len(xs)
    let out: String = "["
    let i: Int = 0
    while i < n {
        if i > 0 { let out = out + "," }
        let out = out + quote_json(native_list_get(xs, i))
        let i = i + 1
    }
    out + "]"
}

fn plugin_to_json(name: String) -> String {
    let parts: [String] = native_list_empty()
    let parts = native_list_append(parts, "\"name\":" + quote_json(get_str(name, "name")))
    let parts = native_list_append(parts, "\"version\":" + quote_json(get_str(name, "version")))
    let parts = native_list_append(parts, "\"description\":" + quote_json(get_str(name, "description")))
    let installed: String = get_str(name, "installed")
    let enabled: String = get_str(name, "enabled")
    let first_party: String = get_str(name, "first_party")
    let parts = native_list_append(parts, "\"installed\":" + installed)
    let parts = native_list_append(parts, "\"enabled\":" + enabled)
    let parts = native_list_append(parts, "\"hooks\":" + hooks_to_json(get_str(name, "hooks")))
    let parts = native_list_append(parts, "\"first_party\":" + first_party)
    "{" + list_join(parts, ",") + "}"
}

fn plugin_list_json() -> String {
    plugin_init()
    let names: [String] = index_list()
    let n: Int = native_list_len(names)
    let out: String = "["
    let i: Int = 0
    while i < n {
        if i > 0 { let out = out + "," }
        let out = out + plugin_to_json(native_list_get(names, i))
        let i = i + 1
    }
    out + "]"
}

fn plugin_get_json(name: String) -> String {
    plugin_init()
    if !index_contains(name) { return "null" }
    plugin_to_json(name)
}

// ── Mutations ────────────────────────────────────────────────────────────────

fn plugin_install(name: String) -> String {
    plugin_init()
    if !index_contains(name) {
        return "{\"error\":\"plugin registry is not available (registry URL not configured)\"}"
    }
    if get_bool(name, "installed") {
        return "{\"error\":\"plugin '" + json_escape_str(name) + "' is already installed\"}"
    }
    put_bool(name, "installed", true)
    put_bool(name, "enabled", true)
    plugin_to_json(name)
}

fn plugin_remove(name: String) -> String {
    plugin_init()
    if !index_contains(name) {
        return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}"
    }
    if str_eq(name, "el-theme-dark") {
        return "{\"error\":\"plugin '" + json_escape_str(name) + "' cannot be removed: it is a required built-in\"}"
    }
    put_bool(name, "installed", false)
    put_bool(name, "enabled", false)
    "{\"ok\":true}"
}

fn plugin_enable(name: String) -> String {
    plugin_init()
    if !index_contains(name) {
        return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}"
    }
    put_bool(name, "enabled", true)
    "{\"ok\":true}"
}

fn plugin_disable(name: String) -> String {
    plugin_init()
    if !index_contains(name) {
        return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}"
    }
    put_bool(name, "enabled", false)
    "{\"ok\":true}"
}

// ── Standalone CLI ───────────────────────────────────────────────────────────

fn host_main() -> Void {
    let argv: [String] = args()
    let n: Int = native_list_len(argv)
    if n == 0 {
        println(plugin_list_json())
        return
    }
    let cmd: String = native_list_get(argv, 0)
    if str_eq(cmd, "list") { println(plugin_list_json()) return }
    if str_eq(cmd, "get") {
        if n >= 2 { println(plugin_get_json(native_list_get(argv, 1))) }
        return
    }
    if str_eq(cmd, "install") {
        if n >= 2 { println(plugin_install(native_list_get(argv, 1))) }
        return
    }
    if str_eq(cmd, "remove") {
        if n >= 2 { println(plugin_remove(native_list_get(argv, 1))) }
        return
    }
    if str_eq(cmd, "enable") {
        if n >= 2 { println(plugin_enable(native_list_get(argv, 1))) }
        return
    }
    if str_eq(cmd, "disable") {
        if n >= 2 { println(plugin_disable(native_list_get(argv, 1))) }
        return
    }
    println("usage: el-plugin-host [list|get|install|remove|enable|disable] <name>")
}

host_main()
