/*
    Official Module `std.formater`
    Library/std/formater/formater.fig

    Copyright © 2025 PuqiAR. All rights reserved.
*/

import std.value; // `type` function and string_from


struct FormatError 
{
    public msg: String;
}

impl Error for FormatError
{
    getErrorClass()
    {
        return "FormatError";
    }
    getErrorMessage()
    {
        return getErrorClass() + ": " + msg;
    }
    toString()
    {
        return getErrorMessage();
    }
}

public func format(objects ...) -> Any
{
    if objects.length() < 1
    {
        throw FormatError{"Require format string"};
    }

    var fmt := objects[0];
    var fmtType := value.type(fmt);
    if fmtType != "String"
    {
        throw FormatError{"arg 0 (fmt) must be String type, got " + fmtType};
    }

    var result := "";
    var argIndex := 1;
    var i := 0;
    var length := fmt.length();

    while (i < length)
    {
        var char := fmt[i];
        
        if char == "{"
        {
            if (i + 1 >= length)
            {
                throw FormatError{"unclosed brace"};
            }
            
            var nextChar = fmt[i + 1];
            
            if nextChar == "{"
            {
                result += "{";
                i += 2;
                continue;
            }
            
            var endIndex := -1;
            for var j = i + 1; j < length; j += 1
            {
                if fmt[j] == "}"
                {
                    endIndex = j;
                    break;
                }
            }
            
            if endIndex == -1
            {
                throw FormatError{"unclosed brace"};
            }
            
            if argIndex >= objects.length()
            {
                throw FormatError{"require enough format expression"};
            }
            
            result += value.string_from(objects[argIndex]);
            argIndex += 1;
            
            i = endIndex + 1;
        }
        else if char == "}"
        {
            if i + 1 < length && fmt[i + 1] == "}"
            {
                result += "}";
                i += 2;
                continue;
            }
            
            throw FormatError{"invalid format syntax"};
        }
        else
        {
            result += char;
            i += 1;
        }
    }
    
    return result;
}

public func formatByListArgs(objects) -> Any
{
    if value.type(objects) != "List"
    {
        return null;
    }
if objects.length() < 1
    {
        throw FormatError{"Require format string"};
    }

    var fmt := objects[0];
    var fmtType := value.type(fmt);
    if fmtType != "String"
    {
        throw FormatError{"arg 0 (fmt) must be String type, got " + fmtType};
    }

    var result := "";
    var argIndex := 1;
    var i := 0;
    var length := fmt.length();

    while (i < length)
    {
        var char := fmt[i];
        
        if char == "{"
        {
            if (i + 1 >= length)
            {
                throw FormatError{"unclosed brace"};
            }
            
            var nextChar = fmt[i + 1];
            
            if nextChar == "{"
            {
                result += "{";
                i += 2;
                continue;
            }
            
            var endIndex := -1;
            for var j = i + 1; j < length; j += 1
            {
                if fmt[j] == "}"
                {
                    endIndex = j;
                    break;
                }
            }
            
            if endIndex == -1
            {
                throw FormatError{"unclosed brace"};
            }
            
            if argIndex >= objects.length()
            {
                throw FormatError{"require enough format expression"};
            }
            
            result += value.string_from(objects[argIndex]);
            argIndex += 1;
            
            i = endIndex + 1;
        }
        else if char == "}"
        {
            if i + 1 < length && fmt[i + 1] == "}"
            {
                result += "}";
                i += 2;
                continue;
            }
            
            throw FormatError{"invalid format syntax"};
        }
        else
        {
            result += char;
            i += 1;
        }
    }
    
    return result;
}