#ifndef __3DENGINEPLUGIN_H__
#define __3DENGINEPLUGIN_H__

#include "DemopajaVersion.h"
#include "PajaTypes.h"
#include "ClassDescC.h"
#include "EffectI.h"
#include "EditableI.h"
#include "UndoC.h"
#include "LayerC.h"
#include "ParamI.h"
#include "ImportableI.h"
#include "ImportableImageI.h"
#include "BBox2C.h"
#include "Matrix2C.h"
#include "TimeContextC.h"
#include "DeviceContextC.h"
#include "DeviceInterfaceI.h"
#include "ImportInterfaceC.h"
#include "OpenGLInterfaceC.h"
#include "Mesh3DC.h"
#include "CameraC.h"
#include "LightC.h"
#include "ScenegraphItemI.h"


const	PluginClass::ClassIdC	CLASS_3DENGINE_EFFECT( 0, 103 );
const	PluginClass::ClassIdC	CLASS_MAS_IMPORT( 0, 202 );



class MASImportC : public Import::ImportableI
{
public:
	static MASImportC*			create_new();
	virtual Edit::DataBlockI*	create();
	virtual Edit::DataBlockI*	create( Edit::EditableI* pOriginal );
	virtual void				copy( Edit::EditableI* pEditable );
	virtual void				restore( Edit::EditableI* pEditable );

	// the interface
	// returns the name of the file this importable refers to
	virtual const char*			get_filename();
	// loads the file
	virtual bool				load_file( const char* szName, Import::ImportInterfaceC* pInterface );

	virtual PluginClass::SuperClassIdC	get_super_class_id();
	virtual PluginClass::ClassIdC		get_class_id();
	virtual const char*					get_class_name();

	virtual PajaTypes::uint32		get_reference_file_count();
	virtual Import::FileHandleC*	get_reference_file( PajaTypes::uint32 ui32Index );

	// interface for this class
	virtual const char*				get_info();
	virtual PluginClass::ClassIdC	get_default_effect();

	virtual PajaTypes::int32	get_duration( PajaSystem::TimeContextC* pTimeContext );
	virtual PajaTypes::float32	get_start_label( PajaSystem::TimeContextC* pTimeContext );
	virtual PajaTypes::float32	get_end_label( PajaSystem::TimeContextC* pTimeContext );

	virtual PajaTypes::uint32	save( FileIO::SaveC* pSave );
	virtual PajaTypes::uint32	load( FileIO::LoadC* pLoad );

	virtual PajaTypes::uint32	get_mesh_count();
	virtual Mesh3DC*			get_mesh( PajaTypes::uint32 ui32Index );

	virtual PajaTypes::uint32	get_scenegraphitem_count();
	virtual ScenegraphItemI*	get_scenegraphitem( PajaTypes::uint32 ui32Index );

	virtual PajaTypes::uint32	get_camera_count();
	virtual CameraC*			get_camera( PajaTypes::uint32 ui32Index );

	virtual PajaTypes::uint32	get_light_count();
	virtual LightC*				get_light( PajaTypes::uint32 ui32Index );

	virtual void				get_time_parameters( PajaTypes::int32& i32FPS, PajaTypes::int32& i32TicksPerFrame, PajaTypes::int32& i32FirstFrame, PajaTypes::int32& i32LastFrame );

protected:
	MASImportC();
	MASImportC( Edit::EditableI* pOriginal );
	virtual ~MASImportC();

private:

	void						count_file_references();
	virtual PajaTypes::uint32	save_scenegraphitem( FileIO::SaveC* pSave, ScenegraphItemI* pItem, PajaTypes::uint32 ui32ParentId, PajaTypes::uint32& ui32Id );
	virtual ScenegraphItemI*	find_parent( ScenegraphItemI* pItem, PajaTypes::uint32 ui32ParentId );
	virtual Mesh3DC*			find_mesh( PajaTypes::uint32 ui32MeshId );

	std::string							m_sFileName;
	std::vector<Mesh3DC*>				m_rMeshes;
	std::vector<ScenegraphItemI*>		m_rScenegraphItems;
	std::vector<CameraC*>				m_rCameras;
	std::vector<LightC*>				m_rLights;
	bool								m_bFileRefsValid;
	std::vector<Import::FileHandleC*>	m_rFileRefs;
	PajaTypes::int32					m_i32FPS;
	PajaTypes::int32					m_i32TicksPerFrame;
	PajaTypes::int32					m_i32FirstFrame;
	PajaTypes::int32					m_i32LastFrame;
};



enum EngineGizmoParamsE {
	ENGINE_PARAM_POS = 0,
	ENGINE_PARAM_PIVOT,
	ENGINE_PARAM_SCALE,
	ENGINE_PARAM_WIDTH,
	ENGINE_PARAM_HEIGHT,
	ENGINE_PARAM_RENDERMODE,
	ENGINE_PARAM_CAMERA,
	ENGINE_PARAM_FPS,
	ENGINE_PARAM_CLEARZ,
	ENGINE_PARAM_FILE,
	ENGINE_PARAM_COUNT,
};


class EngineGizmoC : public Composition::GizmoI
{
public:

	static EngineGizmoC*		create_new( Composition::EffectI* pParent, PajaTypes::uint32 ui32Id );
	virtual Edit::DataBlockI*	create();
	virtual Edit::DataBlockI*	create( Edit::EditableI* pOriginal );
	virtual void				copy( Edit::EditableI* pEditable );
	virtual void				restore( Edit::EditableI* pEditable );

	virtual PajaTypes::int32	get_parameter_count();
	virtual Composition::ParamI*	get_parameter( PajaTypes::int32 i32Index );

	virtual PajaTypes::uint32	save( FileIO::SaveC* pSave );
	virtual PajaTypes::uint32	load( FileIO::LoadC* pLoad );

	virtual void				update_notify( PajaTypes::uint32 ui32ID, PajaTypes::int32 i32Time );

	void						init();
	MASImportC*					get_file();
	PajaTypes::Vector2C			get_pos( PajaTypes::int32 i32Time );
	PajaTypes::Vector2C			get_pivot( PajaTypes::int32 i32Time );
	PajaTypes::Vector2C			get_scale( PajaTypes::int32 i32Time );
	PajaTypes::int32			get_render_mode( PajaTypes::int32 i32Time );
	PajaTypes::int32			get_width( PajaTypes::int32 i32Time );
	PajaTypes::int32			get_height( PajaTypes::int32 i32Time );
	CameraC*					get_camera( PajaTypes::int32 i32Time );
	PajaTypes::int32			get_fps( PajaTypes::int32 i32Time );
	PajaTypes::int32			get_clear_z( PajaTypes::int32 i32Time );

protected:
	EngineGizmoC();
	EngineGizmoC( Composition::EffectI* pParent, PajaTypes::uint32 ui32Id );
	EngineGizmoC( Edit::EditableI* pOriginal );
	virtual ~EngineGizmoC();

private:
	Composition::ParamVector2C*	m_pParamPos;
	Composition::ParamVector2C*	m_pParamScale;
	Composition::ParamVector2C*	m_pParamPivot;
	Composition::ParamIntC*		m_pParamRenderMode;
	Composition::ParamIntC*		m_pParamWidth;
	Composition::ParamIntC*		m_pParamHeight;
	Composition::ParamIntC*		m_pParamCamera;
	Composition::ParamIntC*		m_pParamFps;
	Composition::ParamIntC*		m_pParamClearZ;
	Composition::ParamFileC*	m_pParamFile;
};


//
// transform
//

enum TransformGizmoParamsE {
	TRANSFORM_PARAM_POS = 0,
	TRANSFORM_PARAM_PIVOT,
	TRANSFORM_PARAM_SCALE,
	TRANSFORM_PARAM_COUNT,
};


class TransformGizmoC : public Composition::GizmoI
{
public:

	static TransformGizmoC*			create_new( Composition::EffectI* pParent, PajaTypes::uint32 ui32Id );
	virtual Edit::DataBlockI*		create();
	virtual Edit::DataBlockI*		create( Edit::EditableI* pOriginal );
	virtual void					copy( Edit::EditableI* pEditable );
	virtual void					restore( Edit::EditableI* pEditable );

	virtual PajaTypes::int32		get_parameter_count();
	virtual Composition::ParamI*	get_parameter( PajaTypes::int32 i32Index );

	virtual PajaTypes::uint32		save( FileIO::SaveC* pSave );
	virtual PajaTypes::uint32		load( FileIO::LoadC* pLoad );

	void							init();
	PajaTypes::Vector2C				get_pos( PajaTypes::int32 i32Time );
	PajaTypes::Vector2C				get_pivot( PajaTypes::int32 i32Time );
	PajaTypes::Vector2C				get_scale( PajaTypes::int32 i32Time );

protected:
	TransformGizmoC();
	TransformGizmoC( Composition::EffectI* pParent, PajaTypes::uint32 ui32Id );
	TransformGizmoC( Edit::EditableI* pOriginal );
	virtual ~TransformGizmoC();

private:
	Composition::ParamVector2C*	m_pParamPos;
	Composition::ParamVector2C*	m_pParamScale;
	Composition::ParamVector2C*	m_pParamPivot;
};


//
// attributes
//

enum AttributeGizmoParamsE {
	ATTRIBUTE_PARAM_WIDTH = 0,
	ATTRIBUTE_PARAM_HEIGHT,
	ATTRIBUTE_PARAM_RENDERMODE,
	ATTRIBUTE_PARAM_CAMERA,
	ATTRIBUTE_PARAM_FPS,
	ATTRIBUTE_PARAM_CLEARZ,
	ATTRIBUTE_PARAM_FILE,
	ATTRIBUTE_PARAM_COUNT,
};


class AttributeGizmoC : public Composition::GizmoI
{
public:

	static AttributeGizmoC*			create_new( Composition::EffectI* pParent, PajaTypes::uint32 ui32Id );
	virtual Edit::DataBlockI*		create();
	virtual Edit::DataBlockI*		create( Edit::EditableI* pOriginal );
	virtual void					copy( Edit::EditableI* pEditable );
	virtual void					restore( Edit::EditableI* pEditable );

	virtual PajaTypes::int32		get_parameter_count();
	virtual Composition::ParamI*	get_parameter( PajaTypes::int32 i32Index );

	virtual PajaTypes::uint32		save( FileIO::SaveC* pSave );
	virtual PajaTypes::uint32		load( FileIO::LoadC* pLoad );

	virtual void					update_notify( PajaTypes::uint32 ui32ID, PajaTypes::int32 i32Time );

	void							init();
	MASImportC*						get_file();
	PajaTypes::int32				get_render_mode( PajaTypes::int32 i32Time );
	PajaTypes::int32				get_width( PajaTypes::int32 i32Time );
	PajaTypes::int32				get_height( PajaTypes::int32 i32Time );
	CameraC*						get_camera( PajaTypes::int32 i32Time );
	PajaTypes::int32				get_fps( PajaTypes::int32 i32Time );
	PajaTypes::int32				get_clear_z( PajaTypes::int32 i32Time );

protected:
	AttributeGizmoC();
	AttributeGizmoC( Composition::EffectI* pParent, PajaTypes::uint32 ui32Id );
	AttributeGizmoC( Edit::EditableI* pOriginal );
	virtual ~AttributeGizmoC();

private:
	Composition::ParamIntC*		m_pParamRenderMode;
	Composition::ParamIntC*		m_pParamWidth;
	Composition::ParamIntC*		m_pParamHeight;
	Composition::ParamIntC*		m_pParamCamera;
	Composition::ParamIntC*		m_pParamFps;
	Composition::ParamIntC*		m_pParamClearZ;
	Composition::ParamFileC*	m_pParamFile;
};


enum RenderModeE {
	RENDER_NORMAL = 0,
	RENDER_ADDITIVE = 1,
	RENDER_CARTOON = 2,
};

class EngineEffectC : public Composition::EffectI
{
public:
	static EngineEffectC*			create_new();
	virtual Edit::DataBlockI*		create();
	virtual Edit::DataBlockI*		create( Edit::EditableI* pOriginal );
	virtual void					copy( Edit::EditableI* pEditable );
	virtual void					restore( Edit::EditableI* pEditable );

	virtual PajaTypes::int32		get_gizmo_count();
	virtual Composition::GizmoI*	get_gizmo( PajaTypes::int32 i32Index );

	virtual PluginClass::ClassIdC	get_class_id();
	virtual const char*				get_class_name();

	virtual void					set_default_file( Import::FileHandleC* pHandle );
	virtual Composition::ParamI*	get_default_param( PajaTypes::int32 i32Param );

	virtual void					initialize( PajaSystem::DeviceContextC* pContext, PajaSystem::TimeContextC* pTimeContext );

	virtual void					do_frame( PajaSystem::DeviceContextC* pContext );
	virtual void					eval_state( PajaTypes::int32 i32Time, PajaSystem::TimeContextC* pTimeContext  );
	virtual PajaTypes::BBox2C		get_bbox();

	virtual const PajaTypes::Matrix2C&	get_transform_matrix() const;

	virtual bool					hit_test( const PajaTypes::Vector2C& rPoint );

	virtual PajaTypes::uint32		save( FileIO::SaveC* pSave );
	virtual PajaTypes::uint32		load( FileIO::LoadC* pLoad );

protected:
	EngineEffectC();
	EngineEffectC( Edit::EditableI* pOriginal );
	virtual ~EngineEffectC();

private:

	virtual PajaTypes::uint32		render_item( PajaSystem::OpenGLInterfaceC* pInterface, ScenegraphItemI* pItem, PajaTypes::int32 i32Frame, bool bDrawAdditives );
	virtual PajaTypes::uint32		render_normal( PajaSystem::OpenGLInterfaceC* pInterface, GeomListC* pGList, bool bDrawAdditives );
	virtual void					render_additive( PajaSystem::OpenGLInterfaceC* pInterface, GeomListC* pGList );
	virtual void					render_cartoon_wire( PajaSystem::OpenGLInterfaceC* pInterface, GeomListC* pGList );
	virtual PajaTypes::uint32		render_normal_single_pass( PajaSystem::OpenGLInterfaceC* pInterface, GeomListC* pGList, bool bDrawAdditives );


	EngineGizmoC*		m_pEngineGizmo;
	TransformGizmoC*	m_pTransGizmo;
	AttributeGizmoC*	m_pAttribGizmo;

	PajaTypes::Matrix2C	m_rTM;
	PajaTypes::BBox2C	m_rBBox;
	PajaTypes::Vector2C	m_rVertices[4];
	PajaTypes::int32	m_i32RenderMode;
	PajaTypes::int32	m_i32Time;
	PajaTypes::int32	m_i32Frame;
	PajaTypes::float32	m_f32Aspect;
};


// descprion test effect
class EngineDescC : public PluginClass::ClassDescC
{
public:
	EngineDescC() {};
	virtual ~EngineDescC() {};

	void*						create() { return (void*)EngineEffectC::create_new(); };

	PajaTypes::int32			get_classtype() const { return PluginClass::CLASS_TYPE_EFFECT; };
	PluginClass::SuperClassIdC	get_super_classid() const { return PluginClass::SUPERCLASS_EFFECT; };
	PluginClass::ClassIdC		get_classid() const { return CLASS_3DENGINE_EFFECT; };

	const char*					get_name() const { return "3D Engine"; };
	const char*					get_desc() const { return "3D Engine - Viewer for 3D Scenes"; };

	const char*					get_author_name() const { return "Mikko \"memon\" Mononen"; };
	const char*					get_copyright_message() const { return "Copyright (c) 2000 Moppi Productions"; };
	const char*					get_url() const { return "http://www.moppi.inside.org/demopaja/"; };
	const char*					get_help_filename() const { return "3dengine.html"; };

	bool						check_device_support( PajaSystem::DeviceContextC* pContext )
	{
		if( pContext->query_interface( PajaSystem::INTERFACE_OPENGL ) )
			return true;
		return false;
	}

	// file extension info. (only used in import plugins)
	PajaTypes::uint32			get_ext_count() const { return 0; };
	const char*					get_ext( PajaTypes::uint32 ui32Index ) const { return 0; };
};


// descprion for MAS import
class MASImportDescC : public PluginClass::ClassDescC
{
public:
	MASImportDescC() {};
	virtual ~MASImportDescC() {};

	void*						create() { return (void*)MASImportC::create_new(); };

	PajaTypes::int32			get_classtype() const { return PluginClass::CLASS_TYPE_FILEIMPORT; };
	PluginClass::SuperClassIdC	get_super_classid() const { return PluginClass::SUPERCLASS_IMPORT; };
	PluginClass::ClassIdC		get_classid() const { return CLASS_MAS_IMPORT; };

	const char*					get_name() const { return "MAS 3D Scene"; };
	const char*					get_desc() const { return "Importer for Moppi Ascii (.MAS) 3D Scenes"; };

	const char*					get_author_name() const { return "Mikko \"memon\" Mononen"; };
	const char*					get_copyright_message() const { return "Copyright (c) 2000 Moppi Productions"; };
	const char*					get_url() const { return "http://www.moppi.inside.org/demopaja/"; };
	const char*					get_help_filename() const { return "masimport.html"; };

	bool						check_device_support( PajaSystem::DeviceContextC* pContext )
	{
		if( pContext->query_interface( PajaSystem::INTERFACE_OPENGL ) )
			return true;
		return false;
	}

	// file extension info. (only used in import plugins)
	PajaTypes::uint32			get_ext_count() const { return 1; };
	const char*					get_ext( PajaTypes::uint32 ui32Index ) const
	{
		if( ui32Index == 0 )
			return "mas";
		return 0;
	}
};



#endif // __3DENGINEPLUGIN_H__
