#include "stdafx.h"
#include "glwindow.h"

GLWindow::GLWindow(QWindow *parent)
	: QWindow(parent),
	m_animating(false),
	m_update_pending(false),
	m_context(nullptr),
	m_error(false),
	m_initializing(false)
{
	setSurfaceType(QSurface::SurfaceType::OpenGLSurface);
}

GLWindow::~GLWindow()
{

}

bool GLWindow::initialize()
{
	//nothing here
	return true;
}

void GLWindow::render()
{
	//dummy red background rendering so that we can check if something is off
	glClearColor(1.0f,0.0f,0.0f,1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
}

void GLWindow::renderLater()
{
	//make sure to only queue once
	if (!m_update_pending) {
		m_update_pending = true;
		QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
	}
}

void GLWindow::renderNow()
{
	if(m_error)
		return; //cant render if error occurred	

	if(m_initializing)
		return; //dont allow rendering when we are currently initializing (can happen in some ways like minimizing)

	//no drawing if not exposed
	if (!isExposed())
		return;

	bool needsInitialize = false;

	if (!m_context) {
		m_initializing = true;

		//context creation happens here!
		qDebug()<<"GLWindow requires initialization";
		qDebug()<<"Desired surface format: "<<requestedFormat();
		m_context = new QOpenGLContext(this);
		m_context->setFormat(requestedFormat());

		if(!m_context->create())
		{
			qCritical()<<"OpenGL context creation failed";
			m_error = true;
			emit initializeFailed(tr("OpenGL context creation has failed. VoxelBlur can not be used."));
			return;
		}
		else
		{
			qDebug()<<"OpenGL context created";
		}
		qDebug()<<"Actual surface format: "<<m_context->format();

		needsInitialize = true;
	}

	m_context->makeCurrent(this);

	if (needsInitialize) {
		initializeOpenGLFunctions();
		m_error = !initialize();
		if(m_error)
		{
			//signal should be emitted by subclasses
			qCritical()<<"initialize returned error";
			return;
		}
		m_initializing = false;
	}

	render();

	m_context->swapBuffers(this);

	//if animating, queue another render request
	if (m_animating)
		renderLater();
}

bool GLWindow::event(QEvent *event)
{
	switch (event->type()) {
	case QEvent::UpdateRequest:
		m_update_pending = false;
		renderNow();
		return true;
	default:
		return QWindow::event(event);
	}
}

void GLWindow::exposeEvent(QExposeEvent *event)
{
	Q_UNUSED(event);

	if (isExposed())
		renderNow();
}

QWidget* GLWindow::createWindowContainer(QWidget* parent, Qt::WindowFlags flags)
{
	return QWidget::createWindowContainer(this,parent,flags);
}
