#include "crBatchedLines3D.h"

#include "crGraphicsStats.h"

void crBatchedLines3D::Init()
{
    glGenVertexArrays( 1, &_vao );
    glGenBuffers( 1, &_vbo );

    glBindVertexArray( _vao );
    glBindBuffer( GL_ARRAY_BUFFER, _vbo );

    const GLsizei stride = static_cast<GLsizei>( sizeof( LineVertex ) );
    glEnableVertexAttribArray( 0 );
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<void*>( 0 ) );
    glEnableVertexAttribArray( 1 );
    glVertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<void*>( 12 ) );

    glBindVertexArray( 0 );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );

    _verts.Reserve( INITIAL_RESERVE );
}
void crBatchedLines3D::Cleanup()
{
    glDeleteBuffers( 1, &_vbo );
    glDeleteVertexArrays( 1, &_vao );
    _vbo = 0;
    _vao = 0;
}

void crBatchedLines3D::Begin()
{
    _verts.Clear();
}
void crBatchedLines3D::Line( float3 a, float3 b, color4 color )
{
    LineVertex v;
    v.color = color;

    v.pos = a;
    _verts.Add( v );
    v.pos = b;
    _verts.Add( v );
}
void crBatchedLines3D::Flush( GLuint program, bool depthTest )
{
    const int32_t count = _verts.Size();
    if( count <= 0 )
        return;

    glUseProgram( program );

    if( depthTest )
        glEnable( GL_DEPTH_TEST );
    else
        glDisable( GL_DEPTH_TEST );
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

    glBindVertexArray( _vao );
    glBindBuffer( GL_ARRAY_BUFFER, _vbo );
    glBufferData( GL_ARRAY_BUFFER, static_cast<GLsizeiptr>( count ) * static_cast<GLsizeiptr>( sizeof( LineVertex ) ), _verts.Data(), GL_STREAM_DRAW );

    glDrawArrays( GL_LINES, 0, static_cast<GLsizei>( count ) );

    glBindVertexArray( 0 );

    ++crGraphicsStats::drawCalls;
    crGraphicsStats::vertices += count;

    _verts.Clear();
}
void crBatchedLines3D::ClearUnusedMemory()
{
    _verts.Clear();
    _verts.Shrink();

    glBindBuffer( GL_ARRAY_BUFFER, _vbo );
    glBufferData( GL_ARRAY_BUFFER, 0, nullptr, GL_STREAM_DRAW );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );
}
