#ifndef MagPlus_H
#define MagPlus_H

#include <magics.h>
#include "DriverManager.h"

// undefine the macro ABS because it is defined in mars.h and will be redefined
// by Terralib (only an big issue on AIX)

#undef ABS

#include "OutputHandler.h"
#include "RootSceneNode.h"
#include "MagicsEvent.h"
#include "MagRequest.h"


#if MAGICS_QT
class QGraphicsScene;
#endif

namespace magics {

#if MAGICS_QT
class QtDriver;
#endif

class FortranViewNodeWrapper;

class MagPlus : public stack<BasicSceneObject*>
{
public:
	MagPlus();
	~MagPlus() {}

	void execute(MagRequest&);

	void registerObserver(MagicsObserver* observer) { observers_.push_back(observer); }
	void unregisterObserver(MagicsObserver* observer);
	//! Notify drivers about an event (GUI -> Qt)
	void notifyDrivers(MagicsEvent& event) { drivers_.dispatch(&MagicsEvent::notify, event); }

	//! Notify the magicsobservers about an event in the QtDriverObserver (Qt -> GUI)
	void notify(MagicsEvent&);

#if MAGICS_QT
	//! Set the QGraphicsScene for the Qt driver
	void setQtScene(QGraphicsScene*);
#endif


protected:
	vector<MagicsObserver*> observers_;
	vector<BasicSceneObject*> foreground_;
	
	typedef bool (MagPlus::*ObjectCreator)(magics::MagRequest&);
 
	static map<string,  ObjectCreator > driverCreators_;
	static map<string,  ObjectCreator > sceneCreators_;
	static map<string,  ObjectCreator > sceneUpdators_;
	map<string,  ObjectCreator >* sceneHandler_;
	map<int,  FortranViewNodeWrapper* > pages_;

	void setIconInfo(magics::MagRequest&, MetviewIcon&);

	bool page(magics::MagRequest&);
	bool page_update(magics::MagRequest&);
	bool superpage(magics::MagRequest&);
	bool cartesian(magics::MagRequest&);
	bool coastlines(magics::MagRequest&);
	bool oldcoastlines(magics::MagRequest&);
	bool axis(magics::MagRequest&);
	bool grib(magics::MagRequest&);
	bool gribloop(magics::MagRequest&);
	bool rasterloop(magics::MagRequest&);
	bool bufr(magics::MagRequest&);
	bool visdef(magics::MagRequest&);
	
#if MAGICS_ODB	
	bool geoodb(magics::MagRequest&);
	bool xyodb(magics::MagRequest&);
#endif
	bool geonetcdf(magics::MagRequest&);
	bool xynetcdf(magics::MagRequest&);
	bool geopoints(magics::MagRequest&);
	bool raster(magics::MagRequest&);
	bool input(magics::MagRequest&);
	bool table(magics::MagRequest&);
	bool binning(magics::MagRequest&);

	bool contour(magics::MagRequest&);
	bool symbol(magics::MagRequest&);
	bool wind(magics::MagRequest&);
	bool import(magics::MagRequest&);
	bool obs(magics::MagRequest&);
	bool graph(magics::MagRequest&);
	
	bool ptext(magics::MagRequest&);
	bool text(magics::MagRequest&);
	bool legend(magics::MagRequest&);
	bool ignore(magics::MagRequest&);
	bool device(magics::MagRequest&);

	bool qtdriver(magics::MagRequest&);
	bool pdfdriver(magics::MagRequest&);
	bool pngdriver(magics::MagRequest&);
	bool svgdriver(magics::MagRequest&);
	bool kmldriver(magics::MagRequest&);  
	bool psdriver(magics::MagRequest&);
	bool epsdriver(magics::MagRequest&);
    
	RootSceneNode* root_;
	DriverManager  drivers_;
	OutputHandler  output_;
	int  superpage_;
	bool geographical_;
	MagicsMode mode_;
	enum MetviewMode {creation, update };
	MetviewMode mvMode_;
	FortranViewNodeWrapper* page_;


#if MAGICS_QT
	//! Keep the instance of the QtDrver!
	QtDriver* qtDriver_;
#endif
};

} // namespace magics

#endif
