// organ_cli.el — the organ's command surface. main() lives here.
//
// One binary, the same verbs the Swift program had, and nothing behind them
// except El and two thin device realizers. This file is the proof surface: if
// `organ speak` makes a sound and no Swift binary is in the process tree, the
// claim in organ.el's header is true.
//
// Verbs, and what each one demonstrates:
//
//   grant/revoke/status    the Neuron-level consent lock, inspectable
//   speak <wav>            efferent — audio out of El's own speaker
//   tone <hz> <ms>         own-core synthesis: computed in El, played by El,
//                          never touching the disk
//   say <name> <codes...>  fetch a VOICE FROM THE ENGRAM and render through it
//   listen <sec> <out>     afferent — mic capture, consent-gated, fails closed
//   see <out.jpg>          afferent — one camera frame, same two locks
//   wav-info <wav>         WAV geometry, parsed in El
//   feat-audio <wav>       capture -> compact descriptor (8 numbers)
//   feat-image <jpg>       frame  -> compact scene-geometry
//   voiceprint <wav>       F0 + formants F1-F5 by LPC, in El
//   imitate <in> <out>     LPC analysis-resynthesis, in El
//   hear-imitate <sec>     the closed loop: hear a voice, take its signature,
//                          speak back in it
//   ingest-audio <wav>     descriptor -> engram node (the capture becomes geometry)
//   ingest-voice <wav> <n> voiceprint -> engram voice region (how a voice is learned)
//   converse <manifest>    full-duplex interruptible utterance
//
// The descriptors are the point of the afferent half. A capture is NEVER handed
// on raw: a three-second recording is ~48,000 samples and what leaves this
// process is eight numbers. That is both the privacy rail (the stream stays
// local because only its shape travels) and the reason the engram can hold a
// perception at all — geometry is storable, a waveform is not.

fn cli_usage() -> Bool {
    println("organ — Neuron's I/O organ, native El (own-core, local, consent-gated)")
    println("  grant|revoke <camera|mic>     Neuron-level consent")
    println("  status                        consent + device state")
    println("  speak <file.wav>              play a WAV aloud (efferent)")
    println("  tone [hz] [ms]                synthesize and play, no file at all")
    println("  say <voice> <CODE> [CODE...]  fetch voice FROM THE ENGRAM, render, speak")
    println("  listen <sec> <out.wav>        mic capture 16k mono (afferent)")
    println("  see <out.jpg>                 one camera frame (afferent)")
    println("  wav-info <file.wav>           WAV geometry")
    println("  feat-audio <file.wav>         compact audio descriptor (8 numbers)")
    println("  feat-image                    compact scene-geometry from the camera")
    println("  voiceprint <voice.wav>        F0 + formants F1-F5 (LPC)")
    println("  imitate <in.wav> <out.wav>    LPC analysis-resynthesis")
    println("  hear-imitate <sec> <out.wav>  mic -> signature -> imitate -> speak aloud")
    println("  ingest-audio <file.wav>       descriptor -> engram node (geometry)")
    println("  ingest-voice <voice.wav> <n>  voiceprint -> engram voice region")
    println("  converse <manifest.json> [--authority PM] [--barge-at MS[:kind]] [--live-mic] [--resume]")
    return true
}

// The engram the organ reads and writes. Its own store, never production's.
fn cli_engram_dir() -> String {
    let d: String = env("ORGAN_ENGRAM")
    if str_eq(d, "") {
        return "peripheral/.engram"
    }
    return d
}

fn cli_open_engram() -> Bool {
    let dir: String = cli_engram_dir()
    fs_mkdir(dir)
    let ok: Int = engram_store_boot(dir)
    if ok == 1 {
        return true
    }
    return false
}

// ── formatting helpers ───────────────────────────────────────────────────────

fn cli_f(v: Float, dec: Int) -> String {
    return format_float(v, dec)
}

// ── the descriptor, printed and ingested ─────────────────────────────────────
//
// [seconds, sr, ch, rms, peak, zcr, centroid, f0] — the same eight numbers the
// Swift produced, computed in El, and the compression ratio is the headline:
// a few dozen bytes standing in for a few hundred kilobytes.
fn cli_audio_descriptor_text(v: [Float], path: String) -> String {
    let secs: Float = native_list_get(v, 0)
    let sr: Float = native_list_get(v, 1)
    let ch: Float = native_list_get(v, 2)
    let rms: Float = native_list_get(v, 3)
    let peak: Float = native_list_get(v, 4)
    let zcr: Float = native_list_get(v, 5)
    let cen: Float = native_list_get(v, 6)
    let f0: Float = native_list_get(v, 7)
    return "Heard sound (afferent, mic): " + cli_f(secs, 2) + "s at " + cli_f(sr, 0) + "Hz. RMS energy " + cli_f(rms, 4) + ", peak " + cli_f(peak, 4) + ", zero-crossing rate " + cli_f(zcr, 0) + "Hz, spectral centroid " + cli_f(cen, 0) + "Hz, estimated voice pitch F0 " + cli_f(f0, 0) + "Hz. Compact voice/sound signature (8 numbers) — phonetic geometry seed."
}

fn cli_feat_audio(path: String) -> Bool {
    let v: [Float] = dsp_compute_audio(path)
    if native_list_len(v) < 8 {
        println("{\"ok\": false, \"op\": \"feat-audio\", \"error\": \"cannot read PCM\"}")
        return false
    }
    organ_disclose("FEAT(audio): 8-number signature vs " + int_to_str(float_to_int(native_list_get(v, 0) * native_list_get(v, 1))) + " raw samples.")
    println("{\"ok\": true, \"op\": \"feat-audio\", \"file\": \"" + path + "\", \"seconds\": " + cli_f(native_list_get(v, 0), 4) + ", \"sample_rate\": " + cli_f(native_list_get(v, 1), 0) + ", \"channels\": " + cli_f(native_list_get(v, 2), 0) + ", \"rms\": " + cli_f(native_list_get(v, 3), 6) + ", \"peak\": " + cli_f(native_list_get(v, 4), 6) + ", \"zcr_hz\": " + cli_f(native_list_get(v, 5), 4) + ", \"centroid_hz\": " + cli_f(native_list_get(v, 6), 4) + ", \"f0_hz\": " + cli_f(native_list_get(v, 7), 4) + "}")
    return true
}

fn cli_voiceprint(path: String) -> Bool {
    let v: [Float] = dsp_voiceprint(path)
    if native_list_len(v) < 4 {
        println("{\"ok\": false, \"op\": \"voiceprint\", \"error\": \"cannot read speech\"}")
        return false
    }
    let nf: Int = float_to_int(native_list_get(v, 3))
    let fs: String = ""
    let bs: String = ""
    let i: Int = 0
    while i < nf {
        if i > 0 {
            fs = fs + ", "
            bs = bs + ", "
        }
        fs = fs + cli_f(native_list_get(v, 4 + i * 2), 3)
        bs = bs + cli_f(native_list_get(v, 5 + i * 2), 3)
        i = i + 1
    }
    println("{\"ok\": true, \"op\": \"voiceprint\", \"file\": \"" + path + "\", \"f0_hz\": " + cli_f(native_list_get(v, 0), 4) + ", \"f0_range\": [" + cli_f(native_list_get(v, 1), 4) + ", " + cli_f(native_list_get(v, 2), 4) + "], \"formants_hz\": [" + fs + "], \"bandwidths_hz\": [" + bs + "]}")
    return true
}

// ── main ─────────────────────────────────────────────────────────────────────

fn main() {
    let a: [String] = args()
    let n: Int = native_list_len(a)
    if n < 1 {
        cli_usage()
        return
    }
    let cmd: String = native_list_get(a, 0)

    // ---- consent -----------------------------------------------------------
    if str_eq(cmd, "grant") {
        if n < 2 {
            println("grant needs a device")
            return
        }
        organ_grant(native_list_get(a, 1))
        println("{\"ok\": true, \"op\": \"grant\", \"consent\": \"" + organ_consent_status() + "\"}")
        return
    }
    if str_eq(cmd, "revoke") {
        if n < 2 {
            println("revoke needs a device")
            return
        }
        organ_revoke(native_list_get(a, 1))
        println("{\"ok\": true, \"op\": \"revoke\", \"consent\": \"" + organ_consent_status() + "\"}")
        return
    }
    if str_eq(cmd, "status") {
        println("{\"ok\": true, \"op\": \"status\", \"consent\": \"" + organ_consent_status() + "\", \"speaker\": \"" + speaker_name() + "\", \"speaker_available\": " + int_to_str(speaker_available()) + ", \"mic_os_authorized\": " + int_to_str(mic_available()) + ", \"camera_os_authorized\": " + int_to_str(camera_available()) + "}")
        return
    }

    // ---- efferent ----------------------------------------------------------
    if str_eq(cmd, "speak") {
        if n < 2 {
            println("speak needs a wav")
            return
        }
        let ok: Bool = organ_speak_wav(native_list_get(a, 1))
        println("{\"ok\": " + bool_to_str(ok) + ", \"op\": \"speak\", \"played_aloud\": " + bool_to_str(ok) + "}")
        return
    }
    if str_eq(cmd, "tone") {
        let hz: Int = 220
        let ms: Int = 1000
        if n >= 2 {
            hz = str_to_int(native_list_get(a, 1))
        }
        if n >= 3 {
            ms = str_to_int(native_list_get(a, 2))
        }
        let s: [Int] = organ_tone(hz, ms, 16000)
        let ok: Bool = organ_speak_samples(s, 16000)
        println("{\"ok\": " + bool_to_str(ok) + ", \"op\": \"tone\", \"hz\": " + int_to_str(hz) + ", \"ms\": " + int_to_str(ms) + ", \"samples\": " + int_to_str(native_list_len(s)) + ", \"file\": null}")
        return
    }

    // ---- the voice, from the engram ----------------------------------------
    if str_eq(cmd, "say") {
        if n < 3 {
            println("say needs <voice> <CODE> [CODE...]")
            return
        }
        cli_open_engram()
        let vname: String = native_list_get(a, 1)
        let g: [Int] = organ_voice_fetch(vname)
        if native_list_len(g) < 6 {
            println("{\"ok\": false, \"op\": \"say\", \"error\": \"no voice region '" + vname + "' in the engram\"}")
            return
        }
        // Codes and the phoneme map come from the LANGUAGE side. The organ does
        // not know what a word is and never looks one up.
        let pmap: [String] = ingest_phonetics("elp/data/phonetics.psv")
        let codes: [String] = native_list_empty()
        let i: Int = 2
        while i < n {
            codes = native_list_append(codes, native_list_get(a, i))
            i = i + 1
        }
        let voice: [String] = organ_voice_profile(vname, g)
        let s: [Int] = synth_codes(codes, voice, pmap)
        let ok: Bool = organ_speak_samples(s, 16000)
        println("{\"ok\": " + bool_to_str(ok) + ", \"op\": \"say\", \"voice\": \"" + vname + "\", \"f0\": " + int_to_str(native_list_get(g, 0)) + ", \"kf\": " + int_to_str(native_list_get(g, 2)) + ", \"codes\": " + int_to_str(native_list_len(codes)) + ", \"samples\": " + int_to_str(native_list_len(s)) + "}")
        return
    }

    // ---- afferent ----------------------------------------------------------
    if str_eq(cmd, "listen") {
        if n < 3 {
            println("listen needs <sec> <out.wav>")
            return
        }
        let secs: Int = str_to_int(native_list_get(a, 1))
        let out: String = native_list_get(a, 2)
        if organ_may_listen() == false {
            println("{\"ok\": false, \"op\": \"listen\", \"error\": \"consent denied (fails closed)\"}")
            return
        }
        organ_disclose("MIC: capturing " + int_to_str(secs) + "s (16 kHz mono, LOCAL, never egresses).")
        let s: [Int] = mic_capture_pcm16(secs, 16000)
        let got: Int = native_list_len(s)
        if got <= 0 {
            println("{\"ok\": false, \"op\": \"listen\", \"error\": \"capture returned nothing\"}")
            return
        }
        let ok: Bool = write_wav(s, 16000, out)
        organ_disclose("MIC: captured " + int_to_str(got) + " frames — ready to hand to the ingest organ.")
        println("{\"ok\": " + bool_to_str(ok) + ", \"op\": \"listen\", \"file\": \"" + out + "\", \"frames\": " + int_to_str(got) + ", \"sample_rate\": 16000}")
        return
    }
    if str_eq(cmd, "see") {
        if n < 2 {
            println("see needs an out path")
            return
        }
        if organ_may_see() == false {
            println("{\"ok\": false, \"op\": \"see\", \"error\": \"consent denied (fails closed)\"}")
            return
        }
        organ_disclose("CAMERA: capturing one frame (LOCAL, never egresses).")
        let ok: Int = camera_capture_jpeg(native_list_get(a, 1))
        println("{\"ok\": " + int_to_str(ok) + ", \"op\": \"see\", \"file\": \"" + native_list_get(a, 1) + "\"}")
        return
    }

    // ---- descriptors -------------------------------------------------------
    if str_eq(cmd, "wav-info") {
        if n < 2 {
            println("wav-info needs a wav")
            return
        }
        let p: String = native_list_get(a, 1)
        let w: [Float] = dsp_read_wav(p)
        if dsp_wav_n(w) <= 0 {
            println("{\"ok\": false, \"op\": \"wav-info\"}")
            return
        }
        println("{\"ok\": true, \"op\": \"wav-info\", \"sample_rate\": " + int_to_str(dsp_wav_sr(w)) + ", \"channels\": " + int_to_str(dsp_wav_ch(w)) + ", \"frames\": " + int_to_str(dsp_wav_n(w)) + "}")
        return
    }
    if str_eq(cmd, "feat-audio") {
        if n < 2 {
            println("feat-audio needs a wav")
            return
        }
        cli_feat_audio(native_list_get(a, 1))
        return
    }
    if str_eq(cmd, "feat-image") {
        if organ_may_see() == false {
            println("{\"ok\": false, \"op\": \"feat-image\", \"error\": \"consent denied (fails closed)\"}")
            return
        }
        let f: [Int] = organ_image_descriptor()
        if native_list_len(f) < 15 {
            println("{\"ok\": false, \"op\": \"feat-image\", \"error\": \"no frame\"}")
            return
        }
        let grid: String = ""
        let i: Int = 6
        while i < 15 {
            if i > 6 {
                grid = grid + ", "
            }
            grid = grid + int_to_str(native_list_get(f, i))
            i = i + 1
        }
        println("{\"ok\": true, \"op\": \"feat-image\", \"width\": " + int_to_str(native_list_get(f, 0)) + ", \"height\": " + int_to_str(native_list_get(f, 1)) + ", \"mean_rgb\": [" + int_to_str(native_list_get(f, 2)) + ", " + int_to_str(native_list_get(f, 3)) + ", " + int_to_str(native_list_get(f, 4)) + "], \"brightness_pm\": " + int_to_str(native_list_get(f, 5)) + ", \"luma_grid\": [" + grid + "]}")
        return
    }
    if str_eq(cmd, "voiceprint") {
        if n < 2 {
            println("voiceprint needs a wav")
            return
        }
        cli_voiceprint(native_list_get(a, 1))
        return
    }
    if str_eq(cmd, "imitate") {
        if n < 3 {
            println("imitate needs <in.wav> <out.wav>")
            return
        }
        let s: [Int] = dsp_imitate(native_list_get(a, 1))
        if native_list_len(s) <= 0 {
            println("{\"ok\": false, \"op\": \"imitate\"}")
            return
        }
        let ok: Bool = write_wav(s, 16000, native_list_get(a, 2))
        organ_disclose("IMITATE: rebuilt the voice from its own LPC signature (own-core, no training, no stolen voice).")
        println("{\"ok\": " + bool_to_str(ok) + ", \"op\": \"imitate\", \"out\": \"" + native_list_get(a, 2) + "\", \"samples\": " + int_to_str(native_list_len(s)) + ", \"method\": \"LPC analysis-resynthesis\"}")
        return
    }
    if str_eq(cmd, "hear-imitate") {
        if n < 3 {
            println("hear-imitate needs <sec> <out.wav>")
            return
        }
        let secs: Int = str_to_int(native_list_get(a, 1))
        let out: String = native_list_get(a, 2)
        if organ_may_listen() == false {
            println("{\"ok\": false, \"op\": \"hear-imitate\", \"error\": \"consent denied (fails closed)\"}")
            return
        }
        let heard: String = out + ".heard.wav"
        organ_disclose("HEAR-IMITATE: open the ear, listen " + int_to_str(secs) + "s, take the voice, speak it back.")
        let s: [Int] = mic_capture_pcm16(secs, 16000)
        if native_list_len(s) <= 0 {
            println("{\"ok\": false, \"op\": \"hear-imitate\", \"error\": \"capture returned nothing\"}")
            return
        }
        write_wav(s, 16000, heard)
        let re: [Int] = dsp_imitate(heard)
        if native_list_len(re) <= 0 {
            println("{\"ok\": false, \"op\": \"hear-imitate\", \"error\": \"could not model the voice\"}")
            return
        }
        write_wav(re, 16000, out)
        let ok: Bool = organ_speak_samples(re, 16000)
        println("{\"ok\": " + bool_to_str(ok) + ", \"op\": \"hear-imitate\", \"heard\": \"" + heard + "\", \"out\": \"" + out + "\", \"spoke_aloud\": " + bool_to_str(ok) + "}")
        return
    }

    // ---- the afferent wire: descriptor -> geometry --------------------------
    if str_eq(cmd, "ingest-audio") {
        if n < 2 {
            println("ingest-audio needs a wav")
            return
        }
        let p: String = native_list_get(a, 1)
        let v: [Float] = dsp_compute_audio(p)
        if native_list_len(v) < 8 {
            println("{\"ok\": false, \"op\": \"ingest-audio\"}")
            return
        }
        cli_open_engram()
        let content: String = cli_audio_descriptor_text(v, p)
        let id: String = engram_node(content, "Observation", 70)
        engram_store_checkpoint()
        organ_disclose("INGEST: the capture is now GEOMETRY in the engram (node " + id + ") — the descriptor travelled, the stream did not.")
        println("{\"ok\": true, \"op\": \"ingest-audio\", \"node_id\": \"" + id + "\", \"content\": \"" + content + "\"}")
        return
    }
    if str_eq(cmd, "ingest-voice") {
        if n < 3 {
            println("ingest-voice needs <voice.wav> <name>")
            return
        }
        let p: String = native_list_get(a, 1)
        let name: String = native_list_get(a, 2)
        let v: [Float] = dsp_voiceprint(p)
        if native_list_len(v) < 10 {
            println("{\"ok\": false, \"op\": \"ingest-voice\", \"error\": \"no voiced frames\"}")
            return
        }
        cli_open_engram()
        let f0: Int = float_to_int(native_list_get(v, 0))
        let f1: Int = float_to_int(native_list_get(v, 4))
        let f2: Int = float_to_int(native_list_get(v, 6))
        let f3: Int = float_to_int(native_list_get(v, 8))
        // kf is the vocal-tract scale: this speaker's F1 against the nominal
        // /AA/ F1 of 730 Hz. One number standing for a tract length.
        let kf: Int = 1000 * f1 / 730
        let f0e: Int = f0 * 85 / 100
        let id: String = organ_voice_ingest(name, f0, f0e, kf, f1, f2, f3, "el-organ-lpc-voiceprint", "COARSE")
        engram_store_checkpoint()
        println("{\"ok\": true, \"op\": \"ingest-voice\", \"node_id\": \"" + id + "\", \"name\": \"" + name + "\", \"f0\": " + int_to_str(f0) + ", \"kf\": " + int_to_str(kf) + ", \"f1\": " + int_to_str(f1) + ", \"f2\": " + int_to_str(f2) + ", \"f3\": " + int_to_str(f3) + "}")
        return
    }

    // ---- converse ----------------------------------------------------------
    if str_eq(cmd, "converse") {
        if n < 2 {
            println("converse needs a manifest")
            return
        }
        let mf: String = native_list_get(a, 1)
        let authority: Int = 500
        let barge: Int = 0 - 1
        let kind: String = "bargein"
        let live: Bool = false
        let resume: Bool = false
        let i: Int = 2
        while i < n {
            let f: String = native_list_get(a, i)
            if str_eq(f, "--authority") {
                if i + 1 < n {
                    authority = str_to_int(native_list_get(a, i + 1))
                    i = i + 1
                }
            }
            if str_eq(f, "--barge-at") {
                if i + 1 < n {
                    let spec: String = native_list_get(a, i + 1)
                    let c: Int = str_index_of(spec, ":")
                    if c < 0 {
                        barge = str_to_int(spec)
                    } else {
                        barge = str_to_int(str_slice(spec, 0, c))
                        kind = str_slice(spec, c + 1, str_len(spec))
                    }
                    i = i + 1
                }
            }
            if str_eq(f, "--live-mic") {
                live = true
            }
            if str_eq(f, "--resume") {
                resume = true
            }
            i = i + 1
        }
        let plan: [String] = conv_load_manifest(mf)
        if resume {
            plan = conv_load_resume()
            organ_disclose("CONVERSE: resuming — \"as I was saying...\" (" + int_to_str(plan_count(plan)) + " segments left).")
        } else {
            organ_disclose("CONVERSE: utterance = \"" + conv_utterance(mf) + "\" (" + int_to_str(plan_count(plan)) + " segments).")
        }
        let stopped: Int = conv_run(plan, authority, barge, kind, live)
        println("{\"ok\": true, \"op\": \"converse\", \"stopped_at\": " + int_to_str(stopped) + ", \"complete\": " + bool_to_str(stopped < 0) + "}")
        return
    }

    cli_usage()
}
