/*
 * $Id: _io.h 319 2008-09-24 11:17:38Z kybav1 $
 *
 * Description  : Template for general purpose module.
 * Author       : Vaclav Kyba <mail/Jabber: vaseo1@gmail.com>  <ICQ: 98576293>
 *
 * Purpose      :
 *     Long description of what the file is for.
 */


///
/// Replace all instances of '_io' with your new project name
///

#ifndef __IO_H__
#define __IO_H__

#include "iomodule.h"
#include "textparser.h"
#include "geometrynode.h"
#include "geometrytriangles.h"


namespace VRUT
{
	///Add comment here for your module class
	class _io: public IOModule
	{
	protected:
		///Add any variables
		int var;
		///Add \c var param identificator to register this as parameter
		Parameter::ParameterIdentificator varParamID;

		///Overload this to process events you need
		virtual void processEvent(wxCommandEvent & evt)
		{
			///Always call base method
			IOModule::processEvent(evt);

			switch (evt.GetEventType())
			{
			///Remember to process registered param update events
			case Event::EVT_PARAM_SET:
				UPDATE_PARAM_FROM_EVENT_INT(varParamID, var, evt);
				break;
			}
		}
		///Overload only if you need to do some action every iteration of module's loop
		virtual void run()
		{
			///These actions below usually take place as reaction to events and not in \c run() method
			///Use <className> in all your log messages
			LOG(wxT("<_io>I am still alive"));
			///If using long time operations be sure to check for exit during them
			if (TestExit())
				///If we are to exit return to main loop as soon as possible
				return;
		}

	public:
		///Class constructor - do not alter
		_io(const MODULE_ID & _id, const wxString & _name, EventHandler * msgSink) : IOModule(_id, _name, 0, msgSink)
		{
			var=0;
			///Register your params - choose GUI type or just register w/o GUI
			REGISTER_PARAM_GUI_SLIDER(varParamID, wxT("100"), 0, 200);
		}
		///Class destructor - deinitialize your data
		virtual ~_io()
		{
		}

		///Always overload method giving description for your module
		virtual wxString GetDesc() const
		{
			return wxT("This is my module");
		}
		///IOModule needs to have overloaded method that gives supported extensions
		virtual wxString GetSupportedExts() const
		{
			///Usually only one extension is supported, use spaces if more
			return wxT("NONE1 NONE2 NONE3 FHS");
		}
		///These 2 methods below are called from kernel or invoked by event processing in IOModule
		///All you need to do is overload them
		virtual bool ImportScene(const wxString & fname, SCENE_ID _sceneID, const wxString & rootName)
		{
			///You can use this helper method to get input stream with scene data
			///it automatically decompresses data if an archive is used
			wxInputStream * inputStream = IOModule::GetInputStream(fname);
			if (inputStream)
			{
				///Use \c TextParser instead of wx classes as they are really slow
				TextParser textParser(inputStream, 10000, 1000);
				LOG(wxT("<_io>") + textParser.GetWxLine());
				///Deallocate \c inputStream as \c GetInputStream gives ownership
				SAFE_DELETE(inputStream);
			}

			///Now the fun stuff
			///Create a new geometry node
			SceneNode * node = new GeometryNode(wxT("_io_test"));
			///Insert it to scene using event
			wxCommandEvent evt = Event::GET_EVT_SCENE_NODE_INSERT(_sceneID, node, rootName);
			PostToKernel(evt);
			///Let's create a simple geometry
			GeometryTriangles * geom = new GeometryTriangles(wxT("_io_test_geometry"));
			geom->vertices.push_back(VECTOR3(-1,0,0));
			geom->vertices.push_back(VECTOR3(0,1,0));
			geom->vertices.push_back(VECTOR3(0,0,-1));
			geom->indices.push_back(0);
			geom->indices.push_back(1);
			geom->indices.push_back(2);
			geom->normals.push_back(VECTOR3(0, -1, 0));
			geom->normals.push_back(VECTOR3(0, -1, 0));
			geom->normals.push_back(VECTOR3(0, -1, 0));
			///This describes geometry organization
			///First is indice where the primitive type starts, second is primitive type to use
			std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> triDesc(0, GeometryTriangles::TRI_LIST);
			///More primitive types can be used inside one geometry but usually one is enough
			geom->triDescList.push_back(triDesc);
			///Now add this geometry to scene
			wxCommandEvent evt2 = Event::GET_EVT_SCENE_GEOMETRY_ADD(_sceneID, geom);
			PostToKernel(evt2);
			///We can finally assign geometry to our node
			wxCommandEvent evt3 = Event::GET_EVT_SCENE_NODE_GEOMETRY_SET(_sceneID, wxT("_io_test"), geom->GetName());
			PostToKernel(evt3);

			///Don't forget to inform about our successful import
			wxCommandEvent ev4 = Event::GET_EVT_IO_SCENE_IMPORT_DONE(_sceneID);
			PostToKernel(ev4);

			return true;
		}
		virtual bool ExportScene(const wxString & fname, const Scene * scene)
		{
			if (scene)
				LOG(wxT("<_io>Saving scene '")+scene->GetName()+wxT("' to file '")+fname+wxT("'"));
			///Access \c scene and save its contents to \c fname ...

			return true;
		}
	};
};

#endif
