// epm/src/manifest.el — vessel and package manifest parser
//
// Parses manifest.el files in the vessel/package format:
//
//   vessel "el-auth" {
//       version "0.1.0"
//       description "..."
//       authors ["..."]
//       edition "2026"
//   }
//
//   dependencies {
//       el-platform "1.0"
//       el-identity "0.1"
//   }
//
//   build {
//       entry "src/main.el"
//       output "dist/"
//   }
//
// Parsing is line-by-line string extraction, same approach as elb.el.
// No AST, no grammar — sufficient for well-formed manifests.

// ── String extraction helpers ─────────────────────────────────────────────────

// extract_quoted extracts the first double-quoted token from a string.
// Returns "" if no quoted token is found.
// Example: extract_quoted("vessel \"el-auth\" {") -> "el-auth"
fn extract_quoted(s: String) -> String {
    let first: Int = str_index_of(s, "\"")
    if first < 0 { return "" }
    let after: String = str_slice(s, first + 1, str_len(s))
    let close: Int = str_index_of(after, "\"")
    if close < 0 { return "" }
    return str_slice(after, 0, close)
}

// ── Manifest field extraction ─────────────────────────────────────────────────

// manifest_name extracts the vessel or package name from manifest source.
// Recognises both "vessel" and "package" block headers.
fn manifest_name(src: String) -> String {
    let lines: [String] = str_split(src, "\n")
    let n: Int = native_list_len(lines)
    let i: Int = 0
    while i < n {
        let line: String = native_list_get(lines, i)
        let t: String = str_trim(line)
        if str_starts_with(t, "vessel ") {
            return extract_quoted(t)
        }
        if str_starts_with(t, "package ") {
            return extract_quoted(t)
        }
        let i = i + 1
    }
    return ""
}

// manifest_version extracts the version string from manifest source.
fn manifest_version(src: String) -> String {
    let lines: [String] = str_split(src, "\n")
    let n: Int = native_list_len(lines)
    let i: Int = 0
    while i < n {
        let line: String = native_list_get(lines, i)
        let t: String = str_trim(line)
        if str_starts_with(t, "version ") {
            return extract_quoted(t)
        }
        let i = i + 1
    }
    return ""
}

// manifest_description extracts the description string from manifest source.
fn manifest_description(src: String) -> String {
    let lines: [String] = str_split(src, "\n")
    let n: Int = native_list_len(lines)
    let i: Int = 0
    while i < n {
        let line: String = native_list_get(lines, i)
        let t: String = str_trim(line)
        if str_starts_with(t, "description ") {
            return extract_quoted(t)
        }
        let i = i + 1
    }
    return ""
}

// manifest_entry extracts the build entry file from manifest source.
fn manifest_entry(src: String) -> String {
    let lines: [String] = str_split(src, "\n")
    let n: Int = native_list_len(lines)
    let i: Int = 0
    while i < n {
        let line: String = native_list_get(lines, i)
        let t: String = str_trim(line)
        if str_starts_with(t, "entry ") {
            return extract_quoted(t)
        }
        let i = i + 1
    }
    return ""
}

// manifest_deps extracts dependencies as a JSON array of {"name":..., "version":...} objects.
//
// Scans lines inside the dependencies { ... } block.
// Each dep line looks like:
//   el-platform "1.0"
//
// Returns a JSON array string, e.g.:
//   [{"name":"el-platform","version":"1.0"},{"name":"el-identity","version":"0.1"}]
fn manifest_deps(src: String) -> String {
    let lines: [String] = str_split(src, "\n")
    let n: Int = native_list_len(lines)
    let in_deps: Bool = false
    let result: String = "["
    let count: Int = 0
    let i: Int = 0
    while i < n {
        let line: String = native_list_get(lines, i)
        let t: String = str_trim(line)

        // Detect entry into dependencies block
        if str_eq(t, "dependencies {") {
            let in_deps = true
            let i = i + 1
        } else {
            if in_deps {
                // Detect exit from block
                if str_eq(t, "}") {
                    let in_deps = false
                } else {
                    // Each dep line: name "version"
                    // Find first space to split name from quoted version
                    let sp: Int = str_index_of(t, " ")
                    if sp > 0 {
                        let dep_name: String = str_slice(t, 0, sp)
                        let rest: String = str_trim(str_slice(t, sp, str_len(t)))
                        let dep_ver: String = extract_quoted(rest)
                        if !str_eq(dep_name, "") {
                            let entry: String = "{\"name\":\"" + dep_name + "\",\"version\":\"" + dep_ver + "\"}"
                            if count == 0 {
                                let result = result + entry
                            } else {
                                let result = result + "," + entry
                            }
                            let count = count + 1
                        }
                    }
                }
            }
            let i = i + 1
        }
    }
    return result + "]"
}

// manifest_is_vessel returns true if the manifest declares a vessel (not a package).
fn manifest_is_vessel(src: String) -> Bool {
    let lines: [String] = str_split(src, "\n")
    let n: Int = native_list_len(lines)
    let i: Int = 0
    while i < n {
        let line: String = native_list_get(lines, i)
        let t: String = str_trim(line)
        if str_starts_with(t, "vessel ") { return true }
        let i = i + 1
    }
    return false
}
