#pragma once

#include "volumeshop.h"

#undef emit
#include <ufo/ufo.hpp>
#include <ufo/ux/ux.hpp>
#define emit

#include <QGLWidget>
#include <QPixmap>
#include <QPaintEvent>
#include <QKeyEvent>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QFileInfo>
#include <QLabel>
#include <QToolButton>
#include <QTimer>
#include <QPainter>

#include <list>
#include <map>
#include <vector>

#include "Viewer.h"
#include "Event.h"
#include "RendererPlugin.h"
#include "InteractorPlugin.h"

#include "Environment.h"
#include "Timer.h"

#include "grab.xpm"

class QViewer : public QGLWidget, public Viewer
{
	Q_OBJECT

public:
	QViewer(QWidget *pParent = 0) : QGLWidget(pParent,s_lisViewers.size() == 0 ? NULL : s_lisViewers.back()), m_bDisplayIcons(true)
	{
		s_lisViewers.push_back(this);
		setMinimumSize(128,128);
/*
		QTimer *pTimer = new QTimer( this);
		connect( pTimer, SIGNAL(timeout()), this, SLOT(updateGL()) );
		pTimer->start(5);
*/
		QVBoxLayout *pVerticalLayout = new QVBoxLayout(this);
		pVerticalLayout->addStretch(1);

		QHBoxLayout *pHorizontalLayout = new QHBoxLayout();
		pVerticalLayout->addLayout(pHorizontalLayout);

		m_pToolBar = new QFrame(this);
		
		QHBoxLayout *pToolBarLayout = new QHBoxLayout(m_pToolBar);
		
		pToolBarLayout->setMargin(2);
		pToolBarLayout->setSpacing(2);

		m_pToolBar->setFrameStyle( QFrame::Panel | QFrame::Raised );
		m_pToolBar->setLineWidth( 2 );

		QToolButton *pGrabButton = new QToolButton(m_pToolBar);
		pGrabButton->setIcon(QPixmap(grab_xpm));
		pGrabButton->setAutoRaise(true);		
		pToolBarLayout->addWidget(pGrabButton);
		connect(pGrabButton,SIGNAL(clicked()),SLOT(OnGrab()));
				
		pHorizontalLayout->addWidget(m_pToolBar);
		pHorizontalLayout->addStretch(1);

		setFocusPolicy(Qt::ClickFocus);
		setMouseTracking(true);
	};

	virtual ~QViewer()
	{
		s_lisViewers.remove(this);
	};

	virtual void update()
	{
		QGLWidget::update();
	};

	virtual void bindContext()
	{
		QGLWidget::makeCurrent();
	};

	virtual void releaseContext()
	{
		//doneCurrent();
	};

protected:

	virtual void initializeGL()
	{	
		Viewer::initialize();
		Viewer::reshape(unsigned int(width()),unsigned int(height()));
	};

	virtual void resizeGL(int iWidth, int iHeight) 
	{
		glViewport(0, 0, iWidth, iHeight);

		glPushAttrib(GL_ALL_ATTRIB_BITS);

		glMatrixMode(GL_PROJECTION);
		glPushMatrix();

		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();

		Viewer::reshape(unsigned int(iWidth),unsigned int(iHeight));

		glMatrixMode(GL_PROJECTION);
		glPopMatrix();

		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();

		glPopAttrib();
	};
	
	virtual void paintGL()
	{
		glPushAttrib(GL_ALL_ATTRIB_BITS);
		
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();

		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		Viewer::display();

		glMatrixMode(GL_PROJECTION);
		glPopMatrix();

		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();
	};

	virtual void paintEvent( QPaintEvent *e )
	{
		QGLWidget::paintEvent(e);
	};

	virtual void mousePressEvent ( QMouseEvent * e )
	{			
		const MouseEvent mouEvent(GetMouseEvent(e));
		Viewer::mousePress(mouEvent);
	};

	virtual void mouseReleaseEvent ( QMouseEvent * e )
	{
		const MouseEvent mouEvent(GetMouseEvent(e));
		Viewer::mouseRelease(mouEvent);
	};
	
	virtual void mouseMoveEvent ( QMouseEvent * e )
	{
		const MouseEvent mouEvent(GetMouseEvent(e));
		Viewer::mouseMove(mouEvent);
	};

	virtual void mouseDoubleClickEvent ( QMouseEvent * e )
	{
	};

	virtual void keyPressEvent ( QKeyEvent * e )
	{
		const KeyboardEvent keyEvent(GetKeyboardEvent(e));
		Viewer::keyboardPress(keyEvent);
	};

	virtual void keyReleaseEvent ( QKeyEvent * e )
	{
		const KeyboardEvent keyEvent(GetKeyboardEvent(e));
		Viewer::keyboardRelease(keyEvent);
	};

	const MouseEvent GetMouseEvent (QMouseEvent *e)
	{
		const Vector vecPosition((2.0f * float(e->x()) - float(width())) / float(width()),(float(height()) - 2.0f * float(e->y())) / float(height()),0.0f);
		const int iButton = ((e->button() == Qt::LeftButton) ? MouseEvent::BUTTON_LEFT	: ((e->button() == Qt::MidButton) ? MouseEvent::BUTTON_MIDDLE : ((e->button() == Qt::RightButton) ? MouseEvent::BUTTON_RIGHT : MouseEvent::BUTTON_NONE)));
		const int iStateLeft = (e->buttons () & Qt::LeftButton) ? MouseEvent::STATE_DOWN : MouseEvent::STATE_UP;
		const int iStateRight = (e->buttons () & Qt::MidButton) ? MouseEvent::STATE_DOWN : MouseEvent::STATE_UP;
		const int iStateMiddle = (e->buttons () & Qt::RightButton) ? MouseEvent::STATE_DOWN : MouseEvent::STATE_UP;
		const int iModifiers = ((e->modifiers() & Qt::ShiftModifier) ? KeyboardEvent::MODIFIER_SHIFT : 0) | ((e->modifiers() & Qt::ControlModifier) ? KeyboardEvent::MODIFIER_CTRL : 0) | ((e->modifiers() & Qt::AltModifier) ? KeyboardEvent::MODIFIER_ALT : 0);
		return MouseEvent(vecPosition,iButton,iStateLeft,iStateMiddle,iStateRight,iModifiers);
	};

	const KeyboardEvent GetKeyboardEvent (QKeyEvent *e)
	{
		const int iKey = e->key();
		const int iModifiers = ((e->modifiers() & Qt::ShiftModifier) ? KeyboardEvent::MODIFIER_SHIFT : 0) | ((e->modifiers() & Qt::ControlModifier) ? KeyboardEvent::MODIFIER_CTRL : 0) | ((e->modifiers() & Qt::AltModifier) ? KeyboardEvent::MODIFIER_ALT : 0);
		return KeyboardEvent(iKey,iModifiers);
	};

protected slots:

	void OnGrab()
	{

		m_bDisplayIcons = false;
		m_pToolBar->hide();
		updateGL();

		QImage image = grabFrameBuffer(true);
		m_bDisplayIcons = true;

		updateGL();
		m_pToolBar->show();

		QString strFilename;

		for (unsigned int i=0;i<9999;i++)
		{
			strFilename.sprintf("c:/volumeshop%04d.png",i);
			QFileInfo fi(strFilename);

			if (!fi.exists())
			{
				strFilename = fi.absoluteFilePath();
				break;
			}
		}

		image.save(strFilename,"PNG" );
	};

private:

	QFrame *m_pToolBar;
	bool m_bDisplayIcons;

	static std::list<QViewer*> s_lisViewers;
};