#ifndef ABSTRACTAPP_H
#define ABSTRACTAPP_H

#include <iostream>
#include <string>
#include <qwidget>
using namespace std;

#include "./Context/Context.h"
#include "./exception/Exception.h"
#include "./streams/ErrorStream.h"
#include "./uiSupport/controls.h"

extern ExceptionStream< ostream&, PauseAndExitFunctor  > KODIAK_ERROR;
extern ExceptionStream< ostream&, ContinueFunctor  > KODIAK_PROGRESS;
extern ExceptionStream< ostream&, ContinueFunctor  > KODIAK_WARNING;

///Abstract class for Kodiak OpenGL applications.
/**
*	Abstract class for Kodiak OpenGL applications. 
*	GLwidget forwards messages through this class interface to your applications.
*/
class AbstractAPP
{
private:
	string name;	/**< Name of the application */
	int fps[2];
	bool actualFpsIdx;

	virtual void onOpenGLInit(void)=0; /**<  Is called when OpenGL widget is initialized as postconstructor (OpenGL statements cannot be called before this method (expectially not in APP constructor!!! [because the OpenGL window is not created before this method is called] ) */

public:

	QWidget *myWidget;

	Context *context; 

	string getApplicationName(void);	/**< Returns application name */
	AbstractAPP( const string &appName, Context &context);


	void init(void)	{ this->onOpenGLInit(); }	/**<  Called from OpenGL widget on initialization ) */
	virtual void run(void)=0;	/**<  Is called after calling GLwidget::paintGL() */

	virtual void keyPressEvent( unsigned int key );	/**< Is called when key is pushed down */
	virtual void keyReleaseEvent( unsigned int key );	/**< Is called when key is released */

	virtual void mouseReleaseEvent( unsigned int mouseButton );
	virtual void mousePressEvent( unsigned int mouseButton );
	virtual void mouseMoveEvent( unsigned int posX, unsigned int posY );

	virtual void mouseWheelEvent( int delta );

	virtual void refresh(void);						/**< Its called everytime after calling GL_widghet::updateGL() */

	int getFps(void);
	void setFps(int fps);

	void exceptionTermination( const string& reason, exception &e );

	void initializationStatus( const string& message );
};


#endif