# ━━━ miao_os.ling — the traveling shrine as a LingOS program ━━━━━━━━━━
# The LingOS edition of miao: the same append-only book-of-rites format
# as the lsh shrine (the two interoperate on the same .miao), written
# against ONLY arch-neutral kernel builtins (println, read_file,
# write_file, make_dir, str/list ops, lw_h256, text_hex, now_unix,
# get_args) — no x86-only intrinsics — so one file serves:
#
#   · `ling build . --platform kernel`  a bootable x86-64 miao image
#   · `ling build . --platform rpi`     a bootable Raspberry Pi 5 image
#   · inside LingOS (WM Terminal or Pi shell):
#         ling run <path-to-miao_os.ling> wen
#         ling run <path-to-miao_os.ling> gong sutra.txt
#         ling run <path-to-miao_os.ling> ji the first rite
#
# Booted with no arguments it performs a self-demonstration and rests.
# The shrine lives at /.miao in lingfs. Text spirits only (the kernel
# reads no binaries into .ling). The full temple — deltas, chunks, SSH
# fairs, seals — is desktop miao; see README.md.

fn os_read(p) {
    if file_exists(p) == false { return "" }
    return read_file(p)
}

fn os_hash(content) {
    return lw_h256("miao-shrine", [text_hex(content)])
}

fn os_exists() {
    return len(os_read(".miao/SOUL")) > 0
}

fn os_soul() {
    bind s = os_read(".miao/SOUL")
    if len(s) == 0 { return "main" }
    bind sp = str_find(s, " ")
    return str_trim(str_slice(s, sp + 1, 256))
}

fn os_tip(soul) {
    bind lines = str_split(os_read(".miao/souls"), "\n")
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if str_starts_with(ln, soul + "|") {
            return to_number(str_slice(ln, len(soul) + 1, 16))
        }
        bind i = i + 1
    }
    return 0
}

fn os_set_tip(soul, n) {
    bind lines = str_split(os_read(".miao/souls"), "\n")
    bind out = ""
    bind found = 0
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if len(ln) > 0 {
            if str_starts_with(ln, soul + "|") {
                bind out = out + soul + "|" + num_str(n) + "\n"
                bind found = 1
            } else {
                bind out = out + ln + "\n"
            }
        }
        bind i = i + 1
    }
    if found == 0 { bind out = out + soul + "|" + num_str(n) + "\n" }
    write_file(".miao/souls", out)
    return 1
}

fn os_hash_at(path, n) {
    bind lines = str_split(os_read(".miao/book"), "\n")
    bind best = ""
    bind cur = 0
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if str_starts_with(ln, "===rite|") {
            bind body = str_slice(ln, 8, 4096)
            bind p1 = str_find(body, "|")
            bind cur = to_number(str_slice(body, 0, p1))
        } else if str_starts_with(ln, "---" + path + "|") {
            if cur <= n {
                bind h = str_slice(ln, len(path) + 4, 4096)
                bind sp = str_find(h, "|")
                if sp >= 0 { bind h = str_slice(h, 0, sp) }
                bind best = h
            }
        }
        bind i = i + 1
    }
    return best
}

fn os_content_at(path, n) {
    bind lines = str_split(os_read(".miao/book"), "\n")
    bind best = ""
    bind have = 0
    bind cur = 0
    bind collecting = 0
    bind acc = ""
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if str_starts_with(ln, "===rite|") {
            bind body = str_slice(ln, 8, 4096)
            bind p1 = str_find(body, "|")
            bind cur = to_number(str_slice(body, 0, p1))
            bind collecting = 0
        } else if str_starts_with(ln, "---" + path + "|") {
            if cur <= n {
                if str_find(ln, "|same") >= 0 {
                    bind collecting = 0
                } else {
                    bind collecting = 1
                    bind acc = ""
                }
            } else {
                bind collecting = 0
            }
        } else if str_starts_with(ln, "---end") {
            if collecting == 1 {
                bind best = acc
                bind have = 1
            }
            bind collecting = 0
        } else if collecting == 1 {
            bind acc = acc + str_slice(ln, 1, 65536) + "\n"
        }
        bind i = i + 1
    }
    if have == 0 { return "" }
    return best
}

fn os_kai() {
    if os_exists() {
        println("a shrine already stands here")
        return 0
    }
    write_file(".miao/SOUL", "soul: main")
    write_file(".miao/souls", "main|0\n")
    write_file(".miao/altar", "")
    write_file(".miao/book", "")
    println("* the ground is consecrated -- a traveling shrine stands at /.miao")
    return 1
}

fn os_gong(file) {
    if len(file) == 0 {
        println("usage: miao gong <file>")
        return 0
    }
    bind content = os_read(file)
    if len(content) == 0 {
        println("no such spirit (or empty/binary): " + file)
        return 0
    }
    bind h = os_hash(content)
    bind lines = str_split(os_read(".miao/altar"), "\n")
    bind out = ""
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if len(ln) > 0 {
            if str_starts_with(ln, file + "|") == false { bind out = out + ln + "\n" }
        }
        bind i = i + 1
    }
    write_file(".miao/altar", out + file + "|" + h + "\n")
    println("+ offered " + file)
    return 1
}

fn os_ji(msg) {
    bind altar = os_read(".miao/altar")
    if len(altar) == 0 {
        println("the altar is bare -- gong <file> first")
        return 0
    }
    if len(msg) == 0 {
        println("usage: miao ji <inscription words>")
        return 0
    }
    bind soul = os_soul()
    bind n = os_tip(soul) + 1
    bind entry = "===rite|" + num_str(n) + "|" + num_str(now_unix()) + "|" + soul + "|" + msg + "\n"
    bind lines = str_split(altar, "\n")
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if len(ln) > 0 {
            bind sp = str_find(ln, "|")
            bind file = str_slice(ln, 0, sp)
            bind h = str_slice(ln, sp + 1, 4096)
            if os_hash_at(file, n - 1) == h {
                bind entry = entry + "---" + file + "|" + h + "|same\n---end\n"
            } else {
                bind entry = entry + "---" + file + "|" + h + "\n"
                bind cl = str_split(os_read(file), "\n")
                bind q = 0
                while q < len(cl) {
                    bind entry = entry + " " + list_get(cl, q) + "\n"
                    bind q = q + 1
                }
                bind entry = entry + "---end\n"
            }
        }
        bind i = i + 1
    }
    write_file(".miao/book", os_read(".miao/book") + entry)
    write_file(".miao/altar", "")
    os_set_tip(soul, n)
    println("* rite " + num_str(n) + " sealed on soul " + soul)
    return 1
}

fn os_wen() {
    if os_exists() == false {
        println("no shrine here -- `kai` to consecrate")
        return 0
    }
    bind soul = os_soul()
    println("soul " + soul + " at rite " + num_str(os_tip(soul)))
    bind altar = os_read(".miao/altar")
    if len(altar) == 0 {
        println("the shrine is serene -- the altar is bare")
        return 1
    }
    println("on the altar:")
    bind lines = str_split(altar, "\n")
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if len(ln) > 0 {
            bind sp = str_find(ln, "|")
            println("  " + str_slice(ln, 0, sp))
        }
        bind i = i + 1
    }
    return 1
}

fn os_pu() {
    bind lines = str_split(os_read(".miao/book"), "\n")
    bind shown = 0
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if str_starts_with(ln, "===rite|") {
            bind body = str_slice(ln, 8, 8192)
            bind p1 = str_find(body, "|")
            bind rest = str_slice(body, p1 + 1, 8192)
            bind p2 = str_find(rest, "|")
            bind rest = str_slice(rest, p2 + 1, 8192)
            bind p3 = str_find(rest, "|")
            println("rite " + str_slice(body, 0, p1) + "  [" + str_slice(rest, 0, p3) + "]  " + str_slice(rest, p3 + 1, 8192))
            bind shown = shown + 1
        }
        bind i = i + 1
    }
    if shown == 0 { println("the genealogy is empty -- no rites yet") }
    return 1
}

fn os_hun(arg) {
    if len(arg) == 0 {
        bind cur = os_soul()
        bind lines = str_split(os_read(".miao/souls"), "\n")
        bind i = 0
        while i < len(lines) {
            bind ln = list_get(lines, i)
            if len(ln) > 0 {
                bind sp = str_find(ln, "|")
                bind mark = "o "
                if str_slice(ln, 0, sp) == cur { bind mark = "* " }
                println(mark + ln)
            }
            bind i = i + 1
        }
        return 1
    }
    os_set_tip(arg, os_tip(os_soul()))
    println("new soul kindled: " + arg + "  (zhao " + arg + " to summon it)")
    return 1
}

fn os_zhao(arg) {
    if len(arg) == 0 {
        println("usage: miao zhao <soul | rite-number>")
        return 0
    }
    bind n = to_number(arg)
    bind target = os_soul()
    if n == 0 {
        bind target = arg
        bind n = os_tip(arg)
        write_file(".miao/SOUL", "soul: " + arg)
    }
    bind lines = str_split(os_read(".miao/book"), "\n")
    bind done = ""
    bind restored = 0
    bind i = 0
    while i < len(lines) {
        bind ln = list_get(lines, i)
        if str_starts_with(ln, "---") {
            if str_starts_with(ln, "---end") == false {
                bind body = str_slice(ln, 3, 4096)
                bind sp = str_find(body, "|")
                bind path = str_slice(body, 0, sp)
                if str_find(done, "[" + path + "]") < 0 {
                    bind done = done + "[" + path + "]"
                    bind content = os_content_at(path, n)
                    if len(content) > 0 {
                        write_file(path, content)
                        bind restored = restored + 1
                    }
                }
            }
        }
        bind i = i + 1
    }
    write_file(".miao/altar", "")
    println("* summoned " + target + " at rite " + num_str(n) + " -- " + num_str(restored) + " spirit(s) renewed")
    return 1
}

fn os_xian(arg) {
    bind c = os_content_at(arg, os_tip(os_soul()))
    if len(c) == 0 {
        println("nothing enshrined at: " + arg)
        return 0
    }
    println(c)
    return 1
}

fn os_help() {
    println("miao -- the traveling shrine on LingOS (text spirits only)")
    println("  kai             consecrate a shrine at /.miao      (init)")
    println("  wen             soul, rite, altar                  (status)")
    println("  gong <file>     offer a spirit to the altar        (add)")
    println("  ji <words>      seal the altar into a rite         (commit)")
    println("  pu              read the genealogy                 (log)")
    println("  hun [name]      list souls / kindle one            (branch)")
    println("  zhao <s|n>      summon a soul or rite              (checkout)")
    println("  xian <file>     show a file's enshrined content    (show)")
    println("the desktop temple (deltas, chunks, ssh fairs, seals) is `miao` on win/mac/linux.")
    return 0
}

# boot demonstration: consecrate, seal two rites, read them back
fn os_demo() {
    println("")
    println("==============================================================")
    println("  miao (" + "庙" + ") -- the temple of versions · LingOS appliance")
    println("==============================================================")
    if os_exists() {
        println("a shrine from an earlier boot survives -- its genealogy:")
        os_pu()
        os_wen()
    } else {
        os_kai()
        write_file("sutra.txt", "the incense coil burns in the hall\nthe gate stands open\n")
        os_gong("sutra.txt")
        os_ji("genesis upon lingfs")
        write_file("sutra.txt", "the incense coil burns in the hall\nthe gate stands open\na second verse, sealed on the second boot path\n")
        os_gong("sutra.txt")
        os_ji("the sutra grows")
        println("")
        println("the book of rites now reads:")
        os_pu()
        println("")
        println("summoning rite 1 back:")
        os_zhao("1")
        println("sutra.txt as restored on disk:")
        println(os_read("sutra.txt"))
        os_zhao("2")
    }
    println("")
    println("this image is a self-demonstration. inside full LingOS, run the")
    println("shrine from the Terminal:  ling run <path to miao_os.ling> wen")
    println("the shrine rests.")
    return 0
}

bind start = do {
    bind a = get_args()
    # in-kernel `ling run` gives [found_path, args...]; a boot image gives
    # [name]. desktop interp gives [exe, run, --interp, file, args...].
    bind from = 1
    bind i = 0
    while i < len(a) {
        if str_ends_with(list_get(a, i), ".ling") { bind from = i + 1 }
        bind i = i + 1
    }
    bind cmd = ""
    if from < len(a) { bind cmd = list_get(a, from) }
    bind rest = ""
    bind i = from + 1
    while i < len(a) {
        if rest == "" {
            bind rest = list_get(a, i)
        } else {
            bind rest = rest + " " + list_get(a, i)
        }
        bind i = i + 1
    }
    if cmd == "" {
        os_demo()
    } else if cmd == "kai" || cmd == "init" || cmd == "consecrate" {
        os_kai()
    } else if cmd == "wen" || cmd == "status" || cmd == "divine" {
        os_wen()
    } else if cmd == "gong" || cmd == "add" || cmd == "offer" {
        os_gong(rest)
    } else if cmd == "ji" || cmd == "commit" || cmd == "rite" {
        os_ji(rest)
    } else if cmd == "pu" || cmd == "log" || cmd == "lineage" {
        os_pu()
    } else if cmd == "hun" || cmd == "branch" || cmd == "soul" {
        os_hun(rest)
    } else if cmd == "zhao" || cmd == "checkout" || cmd == "summon" {
        os_zhao(rest)
    } else if cmd == "xian" || cmd == "show" || cmd == "manifest" {
        os_xian(rest)
    } else {
        os_help()
    }
}
