macro package simcu::simapi.macros

import std.ast.*
import std.fs.*
import std.collection.*

/**
 * 编译期宏：从指定 cjpm.toml 读取 version 字段并替换变量声明。
 *
 * 用法：
 * ```
 * @ReadTomlVersion[path: "cjpm.toml"]            // 读取当前包（编译目录）的版本
 * let appVersion: String = ""
 * @ReadTomlVersion[path: "../simapi-cj/cjpm.toml"]  // 读取父包版本
 * let simApiVersion: String = ""
 * ```
 *
 * 说明：宏在编译期执行，工作目录为 cjpm build 的运行目录（应用项目根）。
 * 版本号仅匹配 `version = "x.y.z"`（排除 cjc-version）。
 */
public macro ReadTomlVersion(attr: Tokens, input: Tokens): Tokens {
    var path = "cjpm.toml"
    try {
        let attrText = attr.toString()
        if (let Some(idx) <- attrText.indexOf("path")) {
            let rest = attrText[idx..]
            if (let Some(q1) <- rest.indexOf("\"")) {
                let after = rest[(q1 + 1)..]
                if (let Some(q2) <- after.indexOf("\"")) {
                    path = after[0..q2]
                }
            }
        }
    } catch (_: Exception) {
    }

    var version = "0.0.0"
    try {
        let f = File(path, Read)
        var buf = Array<Byte>(8192, repeat: 0)
        var bytes = ArrayList<Byte>()
        var n = f.read(buf)
        while (n > 0) {
            for (i in 0..n) {
                bytes.add(buf[i])
            }
            n = f.read(buf)
        }
        f.close()
        // 按行解析（version 行是纯 ASCII；避免整体 UTF-8 解码含中文的 description 失败）
        let data = bytes.toArray()
        var lineStart = 0
        for (i in 0..data.size) {
            let isLast = (i == data.size - 1)
            if (data[i] == 10 || isLast) {
                let end = if (data[i] == 10) { i } else { i + 1 }
                let lineBytes = data[lineStart..end]
                let lineText = String.fromUtf8(lineBytes)
                if (!lineText.contains("cjc-version") && lineText.contains("version")) {
                    let parts = lineText.split("\"")
                    if (parts.size >= 2) {
                        version = parts[1]
                    }
                }
                lineStart = i + 1
            }
        }
    } catch (ex: Exception) {
        version = "error:${ex.message}"
    }

    // 生成替换声明：保留原声明的修饰符与变量名，只把值替换为版本号
    // declPrefix 例："public static let" / "private let" / "let"
    var declPrefix = "let"
    var varName = "v"
    try {
        let inputText = input.toString()
        if (let Some(letIdx) <- inputText.indexOf("let")) {
            let prefix = inputText[0..letIdx].trimEnd()
            if (!prefix.isEmpty()) {
                declPrefix = "${prefix} let"
            }
            let rest = inputText[letIdx..]
            let afterLet = rest[3..].trimStart()
            if (let Some(nameEnd) <- afterLet.indexOf(":")) {
                varName = afterLet[0..nameEnd].trimEnd()
            }
        }
    } catch (_: Exception) {
    }

    // 用 cangjieLex 把 "public static let name: String = "version"" 整体解析为 token 流
    let declText = "${declPrefix} ${varName}: String = \"${version}\""
    cangjieLex(declText)
}
