#include "client/rendering/Renderer.h"

Renderer::Renderer(Shader& shader, MatrixStack& stack, Matrix& view) : shader(shader), stack(stack), view(view) {
}

void Renderer::pop() {
    stack.pop();
}

void Renderer::push() {
    stack.push();
}

Renderer& Renderer::update() {
    shader.setMatrix("model", stack.get().getValues());
    return *this;
}

Renderer& Renderer::update(const Vector& pos, const Quaternion& rotation) {
    Matrix m = rotation.toMatrix();
    Vector right(1.0f, 0.0f, 0.0f);
    Vector up(0.0f, 1.0f, 0.0f);
    Vector back(0.0f, 0.0f, -1.0f);
    
    right.mul(m);
    up.mul(m);
    back.mul(m);

    view.set(0, right.getX());
    view.set(1, up.getX());
    view.set(2, back.getX());
    view.set(4, right.getY());
    view.set(5, up.getY());
    view.set(6, back.getY());
    view.set(8, right.getZ());
    view.set(9, up.getZ());
    view.set(10, back.getZ());
    view.set(12, right.dotInverse(pos));
    view.set(13, up.dotInverse(pos));
    view.set(14, back.dotInverse(pos));
    
    shader.setMatrix("view", view.getValues());
    return *this;
}

Renderer& Renderer::scale(float sx, float sy, float sz) {
    stack.get().scale(sx, sy, sz);
    return *this;
}

Renderer& Renderer::scale(float s) {
    stack.get().scale(s);
    return *this;
}

Renderer& Renderer::translate(float tx, float ty, float tz) {
    stack.get().translate(tx, ty, tz);
    return *this;
}

Renderer& Renderer::translateX(float tx) {
    stack.get().translateX(tx);
    return *this;
}

Renderer& Renderer::translateY(float ty) {
    stack.get().translateY(ty);
    return *this;
}

Renderer& Renderer::translateZ(float tz) {
    stack.get().translateZ(tz);
    return *this;
}

Renderer& Renderer::translateTo(float tx, float ty, float tz) {
    stack.get().translateTo(tx, ty, tz);
    return *this;
}

Renderer& Renderer::rotateX(float degrees) {
    stack.get().rotateX(degrees);
    return *this;
}

Renderer& Renderer::rotateY(float degrees) {
    stack.get().rotateY(degrees);
    return *this;
}

Renderer& Renderer::rotateZ(float degrees) {
    stack.get().rotateZ(degrees);
    return *this;
}