// shape_renderer.cpp - Implementació del renderizado de formes
// © 2026 JailDesigner

#include "core/rendering/shape_renderer.hpp"

#include <cmath>

#include "core/rendering/line_renderer.hpp"

namespace Rendering {

    // Helper: transformar un point con rotación, scale i traslación
    static auto transformPoint(const Vec2& point, const Vec2& shape_centre, const Vec2& position, float angle, float scale) -> Vec2 {
        // 1. Centrar el point respecte al centro de la shape
        float centered_x = point.x - shape_centre.x;
        float centered_y = point.y - shape_centre.y;

        // 2. Aplicar scale al point
        float scaled_x = centered_x * scale;
        float scaled_y = centered_y * scale;

        // 3. Aplicar rotación 2D (Z-axis)
        float cos_a = std::cos(angle);
        float sin_a = std::sin(angle);

        float rotated_x = (scaled_x * cos_a) - (scaled_y * sin_a);
        float rotated_y = (scaled_x * sin_a) + (scaled_y * cos_a);

        // 4. Aplicar traslación a posición mundial
        return {.x = rotated_x + position.x, .y = rotated_y + position.y};
    }

    void renderShape(Rendering::Renderer* renderer,
        const std::shared_ptr<Graphics::Shape>& shape,
        const Vec2& position,
        float angle,
        float scale,
        float progress,
        float brightness,
        SDL_Color color) {
        if (!shape || !shape->isValid()) {
            return;
        }
        if (progress < 1.0F) {
            return;
        }

        const Vec2& shape_centre = shape->getCenter();

        for (const auto& primitive : shape->getPrimitives()) {
            if (primitive.type == Graphics::PrimitiveType::POLYLINE) {
                // POLYLINE: conectar puntos consecutivos.
                for (size_t i = 0; i < primitive.points.size() - 1; i++) {
                    const Vec2 P1 = transformPoint(primitive.points[i], shape_centre, position, angle, scale);
                    const Vec2 P2 = transformPoint(primitive.points[i + 1], shape_centre, position, angle, scale);
                    linea(renderer, static_cast<int>(P1.x), static_cast<int>(P1.y), static_cast<int>(P2.x), static_cast<int>(P2.y), brightness, 0.0F, color);
                }
            } else if (primitive.points.size() >= 2) {  // LINE
                const Vec2 P1 = transformPoint(primitive.points[0], shape_centre, position, angle, scale);
                const Vec2 P2 = transformPoint(primitive.points[1], shape_centre, position, angle, scale);
                linea(renderer, static_cast<int>(P1.x), static_cast<int>(P1.y), static_cast<int>(P2.x), static_cast<int>(P2.y), brightness, 0.0F, color);
            }
        }
    }

}  // namespace Rendering
