#include "render.h"
#include "camera.h"
#include <glm/gtc/matrix_transform.hpp>
#include <window.h>

namespace render{

camera::camera():view(_view),proj(_proj)
{
    screenSize = vec2f(0);
    scale = vec3f(1);
}

void camera::bind()
{
    math();
    render::bindCamera(this);
}

const float *camera::getProj() const
{
    return &_proj[0][0];
}

const float *camera::getView() const
{
    return &_view[0][0];
}

const glm::mat4 &camera::getViewMatrix() const
{
    return _view;
}

vec2f camera::screenToWorld(const vec2d &point) const
{
    vec2f size = window::getSize(); // нужно для вычисления позиции курсора, курсор в оконном пространстве
    glm::vec3 r = glm::unProject(glm::vec3(point.x, size.y-point.y, 0), _view, _proj, glm::vec4(0.0, 0.0, size.x, size.y));
    return vec2f(r.x, r.y);
}

void camera2D::math()
{
    vec2f size = screenSize, off = offset;
    vec2f ssize = window::getSize();
    if(size.x == 0)
        size.x = ssize.x;
    if(size.y == 0)
        size.y = ssize.y;

    if(screenSize.x == -1 || screenSize.y == -1)
    {
        if(size.x == -1)
            size.x = size.y*(ssize.x/ssize.y);
        else if(size.y == -1)
            size.y = size.x*(ssize.y/ssize.x);
    }

    if(offset.x == -1 && offset.y == -1)
    {
        off = size*-1;
    }

    _proj = glm::ortho(off.x, size.x, size.y, off.y);
    _proj = glm::scale(_proj, glm::vec3(scale.x, scale.y, scale.z));

    _view = glm::mat4(1);

    _view = glm::rotate(_view, (float)(rotation.x*DTOR), glm::vec3(1, 0, 0));
    _view = glm::rotate(_view, (float)(rotation.y*DTOR), glm::vec3(0, 1, 0));
    _view = glm::rotate(_view, (float)(rotation.z*DTOR), glm::vec3(0, 0, 1));

    _view = glm::translate(_view, glm::vec3(position.x, position.y, position.z));
}

camera3D::camera3D()
{
    fov = 45;
}

void camera3D::math()
{
    vec2f size = screenSize;
    if(size.x == -1)
        size.x = window::getSize().x;
    if(size.y == -1)
        size.y = window::getSize().y;
    _proj = glm::perspective(float(fov*DTOR), size.x/size.y, 0.1f, 100.0f);
    _proj = glm::scale(_proj, glm::vec3(scale.x, scale.y, scale.z));

    _view = glm::mat4(1);



    _view = glm::rotate(_view, (float)(rotation.x*DTOR), glm::vec3(1, 0, 0));
    _view = glm::rotate(_view, (float)(rotation.y*DTOR), glm::vec3(0, 1, 0));
    _view = glm::rotate(_view, (float)(rotation.z*DTOR), glm::vec3(0, 0, 1));

    _view = glm::translate(_view, glm::vec3(position.x, position.y, position.z));
}

void camera3DFlat::math()
{
    vec2f size = screenSize;
    if(size.x == -1)
        size.x = window::getSize().x;
    if(size.y == -1)
        size.y = window::getSize().y;
    _proj = glm::ortho(-8.0f*1.777f, 8.0f*1.777f, -8.0f, 8.0f, .1f, 100.0f);
    _proj = glm::scale(_proj, glm::vec3(scale.x, scale.y, scale.z));

    _view = glm::mat4(1);



    _view = glm::rotate(_view, (float)(rotation.x*DTOR), glm::vec3(1, 0, 0));
    _view = glm::rotate(_view, (float)(rotation.y*DTOR), glm::vec3(0, 1, 0));
    _view = glm::rotate(_view, (float)(rotation.z*DTOR), glm::vec3(0, 0, 1));

    _view = glm::translate(_view, glm::vec3(position.x, position.y, position.z));
}

}
