#include "FinalBuffer.h"
#include "ShaderManager.h"
#include "MatrixManager.h"
#include "DrawFunc.h"

FinalBuffer::FinalBuffer(int nWidth, int nHeight)
{
	this->m_nWidth=nWidth;
	this->m_nHeight=nHeight;

	glEnable(GL_TEXTURE_2D);

	glGenFramebuffers(1,&m_nFrameBuffer);
	glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
	
	glGenTextures(1, &m_nFinalTex);
	glBindTexture(GL_TEXTURE_2D, m_nFinalTex);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_nWidth, m_nHeight, 0, GL_RGBA, GL_FLOAT, 0);
	glBindTexture(GL_TEXTURE_2D, 0);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_nFinalTex, 0);

	// check FbO status
	GLenum FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if(FBOstatus != GL_FRAMEBUFFER_COMPLETE)
	{
		glBindFramebuffer(GL_FRAMEBUFFER, 0); // error
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

FinalBuffer::~FinalBuffer()
{
	glDeleteFramebuffers(1,&m_nFrameBuffer);
}


void FinalBuffer::drawToBuffer(GLuint colorTex, GLuint edgeTex, GLuint lightTex, View *view)
{
	GLSLProgram *glslProgram = ShaderManager::getInstance()->getShader("Final");
	glslProgram->use();

	bind();
	GLenum mrt[] = {GL_COLOR_ATTACHMENT0_EXT};
	glDrawBuffers(1, mrt);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushAttrib( GL_VIEWPORT_BIT );
	glViewport( 0, 0, getWidth(), getHeight());

	MatrixManager::getInstance()->putMatrix4(PROJECTION, glm::mat4(1.0f));
	view->use3D(false);

	glBindAttribLocation(glslProgram->getHandle(), 0, "v_vertex");
	glBindAttribLocation(glslProgram->getHandle(), 1, "v_texture");

	glslProgram->sendUniform("projectionMatrix", &MatrixManager::getInstance()->getMatrix4(PROJECTION)[0][0]);

	glActiveTexture(GL_TEXTURE0); 
	glBindTexture(GL_TEXTURE_2D, colorTex);
	glActiveTexture(GL_TEXTURE1); 
	glBindTexture(GL_TEXTURE_2D, edgeTex);
	glActiveTexture(GL_TEXTURE2); 
	glBindTexture(GL_TEXTURE_2D, lightTex);
	glslProgram->sendUniform("colorTex",0);
	glslProgram->sendUniform("edgeTex",1);
	glslProgram->sendUniform("lightTex",2);

	drawScreenShader(0,0,1.0f,1.0f);

	glslProgram->disable();
	unbind();
	glPopAttrib();
}

void FinalBuffer::bind() 
{
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_nFrameBuffer);
}

void FinalBuffer::unbind() 
{
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

void FinalBuffer::bindFinalTex() 
{
	glBindTexture(GL_TEXTURE_2D, m_nFinalTex);
}

GLuint FinalBuffer::getFinalTex() 
{
	return m_nFinalTex;
}

int FinalBuffer::getWidth() 
{
	return m_nWidth;
}

int FinalBuffer::getHeight() 
{
	return m_nHeight;
}