// bullet_config.cpp - Implementació del parser de BulletConfig
// © 2026 JailDesigner

#include "game/entities/bullet_config.hpp"

#include <cstdint>
#include <exception>
#include <iostream>
#include <string>

namespace {

    auto parseColor(const fkyaml::node& node, SDL_Color& out) -> bool {
        if (!node.is_sequence() || node.size() != 3) {
            return false;
        }
        const auto R = node[0].get_value<uint32_t>();
        const auto G = node[1].get_value<uint32_t>();
        const auto B = node[2].get_value<uint32_t>();
        out = SDL_Color{
            .r = static_cast<uint8_t>(R),
            .g = static_cast<uint8_t>(G),
            .b = static_cast<uint8_t>(B),
            .a = 255};
        return true;
    }

    auto parseShape(const fkyaml::node& node, BulletConfig::ShapeCfg& out) -> bool {
        if (!node.contains("shape") || !node["shape"].contains("path")) {
            std::cerr << "[BulletConfig] Error: falta 'shape.path'\n";
            return false;
        }
        const auto& s = node["shape"];
        out.path = s["path"].get_value<std::string>();
        out.scale = s.contains("scale") ? s["scale"].get_value<float>() : 1.0F;
        out.collision_factor = s.contains("collision_factor")
            ? s["collision_factor"].get_value<float>()
            : 1.0F;
        return true;
    }

    auto parsePhysics(const fkyaml::node& node, BulletConfig::PhysicsCfg& out) -> bool {
        if (!node.contains("physics")) {
            std::cerr << "[BulletConfig] Error: falta 'physics'\n";
            return false;
        }
        const auto& p = node["physics"];
        out.mass = p["mass"].get_value<float>();
        out.restitution = p["restitution"].get_value<float>();
        out.linear_damping = p["linear_damping"].get_value<float>();
        out.angular_damping = p["angular_damping"].get_value<float>();
        out.impact_momentum_factor = p["impact_momentum_factor"].get_value<float>();
        return true;
    }

    auto parseColors(const fkyaml::node& node, BulletConfig::ColorsCfg& out) -> bool {
        if (!node.contains("colors") || !parseColor(node["colors"]["normal"], out.normal)) {
            std::cerr << "[BulletConfig] Error: 'colors.normal' no és [r,g,b]\n";
            return false;
        }
        return true;
    }

}  // namespace

auto BulletConfig::fromYaml(const fkyaml::node& node) -> std::optional<BulletConfig> {
    try {
        BulletConfig cfg;
        cfg.name = node.contains("name") ? node["name"].get_value<std::string>() : "bullet";

        if (!parseShape(node, cfg.shape)) { return std::nullopt; }
        if (!parsePhysics(node, cfg.physics)) { return std::nullopt; }
        if (!parseColors(node, cfg.colors)) { return std::nullopt; }

        return cfg;
    } catch (const std::exception& e) {
        std::cerr << "[BulletConfig] Excepció parsejant: " << e.what() << '\n';
        return std::nullopt;
    }
}
