#pragma once

// ==========================================================
// toml_parser.hpp - Safe Lightweight TOML Configuration Parser
// C++23 Standalone Visual Tool - Poe2VisualTool
// ==========================================================

#include <string>
#include <string_view>
#include "common/string_utils.hpp"

namespace common {

/**
 * @brief Trích xuất giá trị số thực (float) từ một dòng cấu hình TOML.
 */
inline bool ParseTomlFloat(std::string_view line, std::string_view key, float& outVal) noexcept {
    size_t pos = line.find(key);
    if (pos == std::string_view::npos) return false;
    size_t eq = line.find('=', pos);
    if (eq == std::string_view::npos) return false;

    std::string_view valPart = Trim(line.substr(eq + 1));
    if (valPart.empty()) return false;

    try {
        outVal = std::stof(std::string(valPart));
        return true;
    } catch (...) {
        return false;
    }
}

/**
 * @brief Trích xuất giá trị số nguyên có dấu (int) từ một dòng cấu hình TOML.
 */
inline bool ParseTomlInt(std::string_view line, std::string_view key, int& outVal) noexcept {
    size_t pos = line.find(key);
    if (pos == std::string_view::npos) return false;
    size_t eq = line.find('=', pos);
    if (eq == std::string_view::npos) return false;

    std::string_view valPart = Trim(line.substr(eq + 1));
    if (valPart.empty()) return false;

    try {
        outVal = std::stoi(std::string(valPart));
        return true;
    } catch (...) {
        return false;
    }
}

/**
 * @brief Trích xuất giá trị số nguyên không dấu (uint32_t) từ một dòng cấu hình TOML.
 */
inline bool ParseTomlUint(std::string_view line, std::string_view key, uint32_t& outVal) noexcept {
    size_t pos = line.find(key);
    if (pos == std::string_view::npos) return false;
    size_t eq = line.find('=', pos);
    if (eq == std::string_view::npos) return false;

    std::string_view valPart = Trim(line.substr(eq + 1));
    if (valPart.empty()) return false;

    try {
        outVal = static_cast<uint32_t>(std::stoul(std::string(valPart)));
        return true;
    } catch (...) {
        return false;
    }
}

/**
 * @brief Trích xuất giá trị boolean từ một dòng cấu hình TOML.
 */
inline bool ParseTomlBool(std::string_view line, std::string_view key, bool& outVal) noexcept {
    size_t pos = line.find(key);
    if (pos == std::string_view::npos) return false;
    size_t eq = line.find('=', pos);
    if (eq == std::string_view::npos) return false;

    std::string_view valPart = Trim(line.substr(eq + 1));
    std::string v = ToLower(valPart);
    if (v == "true" || v == "1" || v == "yes") {
        outVal = true;
        return true;
    }
    if (v == "false" || v == "0" || v == "no") {
        outVal = false;
        return true;
    }
    return false;
}

/**
 * @brief Trích xuất giá trị chuỗi (string) từ một dòng cấu hình TOML và unescape.
 */
inline bool ParseTomlString(std::string_view line, std::string_view key, std::string& outVal) {
    size_t pos = line.find(key);
    if (pos == std::string_view::npos) return false;
    size_t eq = line.find('=', pos);
    if (eq == std::string_view::npos) return false;

    std::string_view valPart = Trim(line.substr(eq + 1));
    if (valPart.size() >= 2 && ((valPart.front() == '"' && valPart.back() == '"') ||
                                (valPart.front() == '\'' && valPart.back() == '\''))) {
        const char quote = valPart.front();
        valPart = valPart.substr(1, valPart.size() - 2);
        if (quote == '\'') {
            outVal = std::string(valPart);
            return true;
        }
        std::string unescaped;
        unescaped.reserve(valPart.size());
        for (size_t i = 0; i < valPart.size(); ++i) {
            if (valPart[i] == '\\' && i + 1 < valPart.size()) {
                const char next = valPart[i + 1];
                if (next == '\\') { unescaped.push_back('\\'); ++i; }
                else if (next == '"') { unescaped.push_back('"'); ++i; }
                else if (next == 'n') { unescaped.push_back('\n'); ++i; }
                else if (next == 't') { unescaped.push_back('\t'); ++i; }
                else if (next == 'r') { unescaped.push_back('\r'); ++i; }
                else { unescaped.push_back(valPart[i]); }
            } else {
                unescaped.push_back(valPart[i]);
            }
        }
        outVal = unescaped;
        return true;
    }
    outVal = std::string(valPart);
    return true;
}

} // namespace common

using common::ParseTomlFloat;
using common::ParseTomlInt;
using common::ParseTomlUint;
using common::ParseTomlBool;
using common::ParseTomlString;
