/*
 * $Id: iomodule.h 4270 2016-11-06 11:02:47Z antonin.misek-skoda-auto.cz $
 *
 * Description  : One line description of file.
 * Author       : Vaclav Kyba <mail/Jabber: vaseo1@gmail.com>  <ICQ: 98576293>
 *
 * Purpose      :
 *     Long description of what the file is for.
 */


#ifndef __IOMODULE__H__
#define __IOMODULE__H__

#include <wx/archive.h>
//#include <wx/wfstream.h>

#include "VrutApi.h"
#include "scenemodule.h"
//#include "common.h"

namespace VRUT
{
	///Import/export type module - abstract
	class VRUT_CORE_API IOModule : public Module
	{
	protected:
		///Process render event - \c Module overload
		virtual void processEvent(Event *evt)
		{
			Module::processEvent(evt);
			switch (evt->type)
			{
			case Event::EVT_IO_SCENE_IMPORT_DO:
				{
					EventIoSceneImportDo *ev=(EventIoSceneImportDo*)evt;
					smart_pointer_v2<Scene> scene;
					KERNEL->sceneManager->GetScene(scene, ev->sceneID);
					if (scene)
					{
						smart_pointer<SceneNode> root(NULL);
						scene->GetNode(root, ev->rootID);
						if (root)
							ImportScene(ev->sceneFile, ev->sceneID, ev->rootID);
						else
							LOGERROR(wxT("<IOModule>Invalid root node to start import"));
					}
					else
						LOGERROR(wxT("<IOModule>Invalid scene defined to start import"));
				}
				break;
			default:
				break;
			}
		}

	public:
		///Class constructor
		IOModule(const MODULE_ID & _id, const wxString & _name, unsigned _type, Kernel * _kernel) : Module(_id, _name, (_type | MODULE_TYPE_IO ), _kernel)
		{
			REGISTER_LISTENER(Event::EVT_IO_SCENE_IMPORT_DO);
		}
		///Class destructor
		virtual ~IOModule()     {}

		///Get string with file extensions supported by module
		virtual wxString GetSupportedExts() const = 0;
		///Get input stream for given filename (gives ownership)
		static wxInputStream * GetInputStream(const wxString & fname)
		{
			wxFileName wxFname(fname);
			if (!wxFname.FileExists())
			{
				LOGERROR(wxT("<IOModule>File '") + fname + wxT("' not found"));
				return (wxInputStream *)NULL;
			}

			wxInputStream * sceneStream = new wxFileInputStream(wxFname.GetFullPath());

			///Is bzip2 or gzip archive?
			const wxFilterClassFactory * ffactory = wxFilterClassFactory::Find(wxFname.GetFullName(), wxSTREAM_FILEEXT);
			if (ffactory)
			{
				sceneStream = ffactory->NewStream(sceneStream);
				wxFname.SetFullName(ffactory->PopExtension(wxFname.GetFullName()));
			}

			///Is tar or zip archive?
			const wxArchiveClassFactory * afactory = wxArchiveClassFactory::Find(wxFname.GetFullName(), wxSTREAM_FILEEXT);
			if (afactory)
			{
				sceneStream = afactory->NewStream(sceneStream);
				if (sceneStream)
				{
					wxArchiveEntry * entry(((wxArchiveInputStream *)sceneStream)->GetNextEntry());
					if (entry)
					{
						wxFname = wxFileName(entry->GetInternalName());
						((wxArchiveInputStream *)sceneStream)->CloseEntry();
						delete entry;
					}
				}
			}

			if (!sceneStream || !sceneStream->IsOk())
			{
				LOGERROR(wxT("<IOModule>File '") + fname + wxT("' cannot be read"));
				SAFE_DELETE(sceneStream);
				return (wxInputStream *)NULL;
			}

			return sceneStream;
		}
		///Import scene from file
		///\param[in] fname Path to scene files (archive)
		///\param[in] _sceneID ID of scene to be filled with data
		///\param[in] rootID ID of node where to start filling
		///\return \c True if successful
		virtual bool ImportScene(const wxString & fname, SCENE_ID _sceneID, const NODE_ID &rootID) = 0;
		///Export scene to file
		virtual bool ExportScene(smart_pointer_v2<Scene> &scene, const NODE_ID rootID, const wxString &fname) = 0;
	};
}

#endif
