#include "rendering/VertexBuffer.h"

VertexBuffer::Attributes& VertexBuffer::Attributes::addFloat(int count) {
    attributes.add(GL::Attribute::newFloat(count));
    return *this;
}

VertexBuffer::Attributes& VertexBuffer::Attributes::addColor4() {
    attributes.add(GL::Attribute::newColor(4));
    return *this;
}

VertexBuffer::Attributes& VertexBuffer::Attributes::addSpacer() {
    attributes.add(GL::Attribute::newDummy());
    return *this;
}

void VertexBuffer::Attributes::set() const {
    int size = 0;
    for(const GL::Attribute& a : attributes) {
        size += a.getSize();
    }
    int index = 0;
    int offset = 0;
    for(const GL::Attribute& a : attributes) {
        if(!a.isDummy()) {
            GL::vertexAttribPointer(index, a, size, offset);
        }
        offset += a.getSize();
        index++;
    }
}

VertexBuffer::VertexBuffer() : vertexArray(0), vertexBuffer(0), size(0) {
}

VertexBuffer::~VertexBuffer() {
    GL::deleteBuffer(vertexBuffer);
    GL::deleteVertexArray(vertexArray);
}

void VertexBuffer::bindArray() const {
    GL::bindVertexArray(vertexArray);
}

void VertexBuffer::bindBuffer() const {
    GL::bindBuffer(vertexBuffer);
}

void VertexBuffer::init(const Attributes& attributes) {
    if(vertexArray != 0 || vertexBuffer != 0) {
        return;
    }
    vertexArray = GL::genVertexArray();
    vertexBuffer = GL::genBuffer();
    bindArray();
    bindBuffer();
    attributes.set();
}

void VertexBuffer::setStaticData(int size, const void* data) {
    VertexBuffer::size = size;
    bindBuffer();
    GL::bufferDataStatic(size, data);
}

void VertexBuffer::setStreamData(int size, const void* data) {
    VertexBuffer::size = size;
    bindBuffer();
    GL::bufferDataStream(size, data);
}

void VertexBuffer::setDynamicData(int size, const void* data) {
    VertexBuffer::size = size;
    bindBuffer();
    GL::bufferDataDynamic(size, data);
}

void VertexBuffer::updateData(int offset, int size, const void* data) {
    bindBuffer();
    GL::bufferSubData(offset, size, data);
}

void VertexBuffer::draw(int vertices, int offset) {
    bindArray();
    GL::drawTriangles(offset, vertices);
}

void VertexBuffer::drawStrip(int vertices, int offset) {
    bindArray();
    GL::drawTriangleStrip(offset, vertices);
}

void VertexBuffer::drawPoints(int vertices, int offset) {
    bindArray();
    GL::drawPoints(offset, vertices);
}

int VertexBuffer::getSize() const {
    return size;
}