#include "renderer_ray_tracer.hpp"

#include <vector>
#include "glm/glm.hpp"
#include "glm/vec2.hpp"
#include "glm/vec3.hpp"
#include "glm/gtc/type_ptr.hpp"

static const char *vss =
#include "raycaster.vs"
;

static const char *fss =
#include "raycaster.fs"
;


namespace endofthejedi {
    RendererRayTracer::RendererRayTracer()
    {
    }

    void RendererRayTracer::setup()
    {
        m_shader.init();
        m_shader.load(vss, GL_VERTEX_SHADER);
        m_shader.load(fss, GL_FRAGMENT_SHADER);
    }

    void RendererRayTracer::render(const game::State *state) {
        m_shader.bind();

        std::vector<glm::vec3> positions;
        std::vector<glm::vec4> colors;
        std::vector<GLfloat> radii;
        std::vector<GLfloat> reflections;

        for (const game::Planet *planet : state->planets) {
            positions.push_back(glm::vec3(planet->position, -5.0f));
            radii.push_back(planet->radius);
            colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
        }

        for (const game::Ship *ship : state->ships) {
            positions.push_back(glm::vec3(ship->position, -3.0f));
            radii.push_back(ship->radius);
            colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
        }

        for (const game::Player *player : state->players) {
            for (const game::Missile *missile : player->missiles) {
                positions.push_back(glm::vec3(missile->position, -3.0f));
                radii.push_back(0.01f);
                colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
            }
        }

        for (auto &pos : positions) {
            pos.x *= 5;
            pos.y *= 5;
        }
        for (auto &rad : radii) {
            rad *= 5;
        }

        /*
        for (const game::Trace *trace : state->traces) {
          positions.push_back(glm::vec3(trace->position, -3.0f));
          radii.push_back(trace->radius);
          colors.push_back(glm::vec4(0.0f, 1.0f, 0.0f, 0.5f));
          }*/

        glUniform1f(m_shader.location("aspectratio"), 1.0f);
        glUniform1i(m_shader.location("reflections"), 1);
        glUniform3f(m_shader.location("l_position"), 0.6f, 0.1f, 0.0f);
        glUniform1f(m_shader.location("l_radius"), 1.0f);
        glUniform3fv(m_shader.location("s_positions"), positions.size(),
                     glm::value_ptr(positions[0]));

        glUniform4fv(m_shader.location("s_colors"), colors.size(),
                     glm::value_ptr(colors[0]));

        glUniform1fv(m_shader.location("s_radii"), radii.size(), &radii[0]);
        glUniform1i(m_shader.location("s_length"), positions.size());

        // render fullscreen quad with legacy opengl (too lazy, sorry)
        glBegin(GL_QUADS);
        glVertex2f(-1.0f, -1.0f);
        glVertex2f(1.0f, -1.0f);
        glVertex2f(1.0f, 1.0f);
        glVertex2f(-1.0f, 1.0f);
        glEnd();
    }
}
