#pragma once
#include <PSX/GPU/gpu_primitives.hpp>
#include <PSX/GPU/gpu.hpp>
#include <PSX/GTE/gte.hpp>

#include <stdio.hpp>

namespace GTETest {
    using namespace JabyEngine;

    struct GTE_Sprite {
        GPU::AreaI16          area;
        GPU::PositionI16      pivot;
        deg_t                 angle;
        gte_float             scale;
        GPU::POLY_FT4::Linked display;

        static constexpr GTE_Sprite create(const GPU::POLY_FT4::Linked& base) {
            const auto rect_size = base->get_rect_size();
            return GTE_Sprite{
                .area    = GPU::AreaI16::create(base->get_rect_pos(), rect_size),
                .pivot   = GPU::PositionI16::create(rect_size.width/2, rect_size.height/2),
                .angle   = 0.0_deg,
                .scale   = 1.0_gf,
                .display = base
            };
        }

        void apply(const GTE::MATRIX& gbl_matrix = GTE::MATRIX::identity()) {
            const auto matrix = 
                GTE::MATRIX::translated(-this->pivot.x, -this->pivot.y, 0)
                .rotate(0.0_deg, 0.0_deg, this->angle)
                .scale(this->scale, this->scale)
                .translate(this->area.position.x + this->pivot.x, this->area.position.y + this->pivot.y, 0)
                .comp(gbl_matrix);

            this->display->vertex0 = matrix.apply_to(GPU::Vertex::create(0,                                          0)); 
            this->display->vertex1 = matrix.apply_to(GPU::Vertex::create(this->area.size.width,                      0)); 
            this->display->vertex2 = matrix.apply_to(GPU::Vertex::create(0,                     this->area.size.height)); 
            this->display->vertex3 = matrix.apply_to(GPU::Vertex::create(this->area.size.width, this->area.size.height)); 
        }

        void render() {
            GPU::render(this->display);
        }
    };
}