// epm/src/epm.el — El Package Manager entry point
//
// epm manages vessels: the deployable, versioned units of El code.
// Vessels are stored in Engram (the graph database) and installed locally
// under .epm/vessels/.
//
// Usage:
//   epm publish                   # publish current project to registry
//   epm install                   # install all dependencies from manifest.el
//   epm install <vessel>          # install a specific vessel
//   epm list                      # list all vessels in the registry
//   epm info <vessel>             # show metadata for a vessel
//   epm info <vessel> <version>   # show metadata for a specific version
//
// Configuration (environment):
//   ENGRAM_URL   — Engram base URL (default: http://localhost:8742)
//
// Import order: manifest.el, registry.el, install.el must be compiled first.
// This file imports all three and is the build entry point.

import "manifest.el"
import "registry.el"
import "install.el"

// ── Subcommand handlers ───────────────────────────────────────────────────────

// cmd_publish reads manifest.el from the current directory and publishes
// the vessel/package to the Engram registry.
fn cmd_publish() -> Void {
    let src: String = fs_read("manifest.el")
    if str_eq(src, "") {
        println("epm: no manifest.el found in current directory")
        exit(1)
    }

    let name: String = manifest_name(src)
    if str_eq(name, "") {
        println("epm: manifest.el has no 'vessel' or 'package' declaration")
        exit(1)
    }

    let version: String = manifest_version(src)
    if str_eq(version, "") {
        println("epm: manifest.el has no 'version' declaration")
        exit(1)
    }

    let description: String = manifest_description(src)
    let entry: String       = manifest_entry(src)
    let deps_json: String   = manifest_deps(src)

    println("epm: publishing " + name + " " + version + " ...")

    let node_id: String = registry_publish(name, version, description, entry, deps_json)
    if str_eq(node_id, "") {
        println("epm: publish failed")
        exit(1)
    }

    println("epm: published " + name + " " + version + " (node: " + node_id + ")")
}

// cmd_install_named installs a specific vessel by name (with optional version).
// Expects: install <name> or install <name>@<version>
fn cmd_install_named(spec: String) -> Void {
    // spec may be "el-auth" or "el-auth@0.1.0"
    let at: Int = str_index_of(spec, "@")
    let vname: String = spec
    let vver: String  = ""
    if at > 0 {
        let vname = str_slice(spec, 0, at)
        let vver  = str_slice(spec, at + 1, str_len(spec))
    }

    println("epm: installing " + vname + " ...")

    let mk1: Int = exec_command("mkdir -p .epm/vessels")
    let ok: Bool = install_vessel(vname, vver)
    if !ok {
        println("epm: install failed")
        exit(1)
    }
}

// cmd_list prints all vessels registered in Engram.
fn cmd_list() -> Void {
    println("epm: fetching vessel list from registry ...")
    let raw: String = registry_list()
    let n: Int = json_array_len(raw)

    if n == 0 {
        println("epm: no vessels found in registry")
        return
    }

    println("epm: " + native_int_to_str(n) + " vessel(s) in registry:")
    println("")

    let i: Int = 0
    while i < n {
        // Each element is a quoted+escaped content JSON blob
        let elem: String    = json_array_get_string(raw, i)
        let vname: String   = json_get_string(elem, "name")
        let vver: String    = json_get_string(elem, "version")
        let vdesc: String   = json_get_string(elem, "description")
        println("  " + vname + " " + vver + "  — " + vdesc)
        let i = i + 1
    }
}

// cmd_info prints detailed metadata for a specific vessel.
// argv is the full args list; idx is the position of the vessel name.
fn cmd_info(argv: [String], idx: Int) -> Void {
    let argc: Int = native_list_len(argv)
    if idx >= argc {
        println("epm: usage: epm info <vessel> [version]")
        exit(1)
    }

    let vname: String = native_list_get(argv, idx)
    let vver: String  = ""
    if idx + 1 < argc {
        let vver = native_list_get(argv, idx + 1)
    }

    let content: String = registry_find(vname, vver)
    if str_eq(content, "") {
        println("epm: vessel '" + vname + "' not found in registry")
        exit(1)
    }

    let name: String   = json_get_string(content, "name")
    let ver: String    = json_get_string(content, "version")
    let desc: String   = json_get_string(content, "description")
    let entry: String  = json_get_string(content, "entry")
    let deps_raw: String = json_get_raw(content, "deps")

    println("name:        " + name)
    println("version:     " + ver)
    println("description: " + desc)
    println("entry:       " + entry)

    let dep_n: Int = json_array_len(deps_raw)
    if dep_n == 0 {
        println("dependencies: (none)")
    } else {
        println("dependencies:")
        let di: Int = 0
        while di < dep_n {
            let dep: String      = json_array_get(deps_raw, di)
            let dep_name: String = json_get_string(dep, "name")
            let dep_ver: String  = json_get_string(dep, "version")
            println("  " + dep_name + " " + dep_ver)
            let di = di + 1
        }
    }
}

// ── Main ──────────────────────────────────────────────────────────────────────

fn main() -> Void {
    let argv: [String] = args()
    let argc: Int = native_list_len(argv)

    // argv[0] is the program name; subcommand is argv[1]
    if argc < 2 {
        println("epm — El Package Manager")
        println("")
        println("usage:")
        println("  epm publish                  publish current project to registry")
        println("  epm install                  install all dependencies (from manifest.el)")
        println("  epm install <vessel>         install a specific vessel")
        println("  epm install <vessel>@<ver>   install a specific vessel at a version")
        println("  epm list                     list all vessels in the registry")
        println("  epm info <vessel>            show vessel metadata")
        println("  epm info <vessel> <version>  show metadata for a specific version")
        println("")
        println("configuration:")
        println("  ENGRAM_URL   Engram base URL (default: http://localhost:8742)")
        exit(0)
    }

    let sub: String = native_list_get(argv, 1)

    if str_eq(sub, "publish") {
        cmd_publish()
        return
    }

    if str_eq(sub, "install") {
        if argc >= 3 {
            let spec: String = native_list_get(argv, 2)
            cmd_install_named(spec)
        } else {
            cmd_install()
        }
        return
    }

    if str_eq(sub, "list") {
        cmd_list()
        return
    }

    if str_eq(sub, "info") {
        cmd_info(argv, 2)
        return
    }

    println("epm: unknown subcommand '" + sub + "'")
    println("run 'epm' with no arguments for usage")
    exit(1)
}
