// Fmt.bux — String formatting with positional placeholders {0}, {1}, {2}...
//
// Usage:
//   Fmt_Fmt1("Hello, {0}!", "World")
//   Fmt_FmtInt("Count: {0}", 42)
//   Fmt_FmtBool("Active: {0}", true)
//   Fmt_Fmt2("Name: {0}, Age: {1}", name, String_FromInt(age))

module Std::Fmt {

import Std::String::{
    String_Eq,
    String_FromInt,
    String_FromFloat,
    String_FromBool,
    StringBuilder,
    StringBuilder_New,
    StringBuilder_Append,
    StringBuilder_Build,
    String_Chars
};

extern func bux_strlen(s: String) -> uint;
extern func bux_str_to_int(s: String) -> int64;
extern func bux_alloc(size: uint) -> *void;

// Core formatting engine: replace {0}..{9} in template with args
func Fmt_Format(tmpl: String, argStrs: *String, argCount: int) -> String {
    let sb: StringBuilder = StringBuilder_New();
    var i: uint = 0;
    let tmplLen: uint = bux_strlen(tmpl);
    while i < tmplLen {
        // Check for {
        let ch: String = String_Chars(tmpl, i);
        if String_Eq(ch, "{") {
            let digitIdx: uint = i + 1;
            if digitIdx < tmplLen {
                let digitCh: String = String_Chars(tmpl, digitIdx);
                let d: int64 = bux_str_to_int(digitCh);
                if d >= 0 && d < argCount as int64 {
                    // Consume {d}
                    i = i + 2; // skip past digit
                    // Check for closing }
                    if i < tmplLen {
                        let closeCh: String = String_Chars(tmpl, i);
                        if String_Eq(closeCh, "}") {
                            i = i + 1; // skip }
                            let argStr: String = argStrs[d as uint];
                            StringBuilder_Append(&sb, argStr);
                            continue;
                        }
                    }
                }
            }
        }
        // Normal character: append it
        StringBuilder_Append(&sb, ch);
        i = i + 1;
    }
    return StringBuilder_Build(&sb);
}

// Convenience wrappers
func Fmt_Fmt1(tmpl: String, a1: String) -> String {
    var args: *String = bux_alloc(sizeof(String)) as *String;
    args[0] = a1;
    return Fmt_Format(tmpl, args, 1);
}

func Fmt_FmtInt(tmpl: String, val: int64) -> String {
    let s: String = String_FromInt(val);
    return Fmt_Fmt1(tmpl, s);
}

func Fmt_FmtBool(tmpl: String, val: bool) -> String {
    let s: String = String_FromBool(val);
    return Fmt_Fmt1(tmpl, s);
}

func Fmt_FmtFloat(tmpl: String, val: float64) -> String {
    let s: String = String_FromFloat(val);
    return Fmt_Fmt1(tmpl, s);
}

func Fmt_Fmt2(tmpl: String, a1: String, a2: String) -> String {
    var args: *String = bux_alloc(2 * sizeof(String)) as *String;
    args[0] = a1;
    args[1] = a2;
    return Fmt_Format(tmpl, args, 2);
}

func Fmt_Fmt3(tmpl: String, a1: String, a2: String, a3: String) -> String {
    var args: *String = bux_alloc(3 * sizeof(String)) as *String;
    args[0] = a1;
    args[1] = a2;
    args[2] = a3;
    return Fmt_Format(tmpl, args, 3);
}

}
