#ifndef _H_DFENGINEHEADER_H
#define _H_DFENGINEHEADER_H

//=========== (C) Copyright 2004-2005 DoubleFusion LTD. All rights reserved. ======
//
// File: DFEngineHeader.h
//
// *** DOUBLE FUSION PROPRIETARY INFORMATION ***
//============================================================================

#ifndef DF_DONOT_DEFINE_TYPES

#ifdef _WIN32
#pragma once
#endif

#ifdef _WIN32
#define DF_WINDOWS
#ifdef _DEBUG
#define DF_DEBUG
#endif
#elif defined PS2
#define DF_PS2
#endif

/// Basic types

typedef signed char      DF_Int8;
typedef signed short     DF_Int16;
typedef signed int		 DF_Int32;

#ifdef _WIN32
#ifdef _MSC_VER
typedef signed __int64   DF_Int64;
#endif
#elif (defined _LINUX || defined LINUX)
typedef long long	DF_Int64;
#elif defined PS2
typedef long long DF_Int64;
#else
#error "Unsupported Platform."
#endif

typedef unsigned char      DF_UInt8;
typedef unsigned short     DF_UInt16;
typedef unsigned int	   DF_UInt32;

#ifdef _WIN32
#ifdef _MSC_VER
typedef unsigned __int64   DF_UInt64;
#endif
#elif (defined _LINUX || defined LINUX)
typedef unsigned long long DF_UInt64;
#elif defined PS2
typedef unsigned long long DF_UInt64;
#else
#error "Unsupported Platform."
#endif


typedef float  DF_Float32;
typedef double DF_Float64;

typedef unsigned int DF_UInt;

typedef DF_UInt32	DF_Time;
typedef char* String;
typedef const char* ConstString;

// error code returned from most DF functions
typedef long DF_RESULT;

// df object handles
typedef void* DFObjectHandle;
typedef DFObjectHandle* lpDFObjectHandle;

typedef enum 
{
	DF_OK = 0,
	DF_ERROR = -1,
	DF_ERROR_NOTSTARTED = -2,
	DF_ERROR_OPENFILE = -3,
	DF_ERROR_WRONG_VERSION = -4,
	DF_ERROR_ALREADY_STARTED = -5,
	DF_ERROR_INVALID_OBJECT_ID = -6,
	DF_ERROR_INVALID_ZONE_ID = -7,
	DF_ERROR_INVALID_ROOT_FOLDER = -8,
	DF_ERROR_NOT_IMPLEMENTED = -9,
	DF_ERROR_USER_SHUTDOWN = -10,
	DF_ERROR_LOGIN_COMM = -11,
	DF_ERROR_LOGIN_SERVER = -12,
	DF_OK_LOGGING_TO_SERVER = 1,
	DF_ERROR_CREATIVE_DL_COMM = -13,
	DF_ERROR_CREATIVE_DL_SERVER = -14,
	DF_OK_CREATIVE_DOWNLOADING = 2,
	DF_ERROR_TRACKING_COMM = -15,
	DF_ERROR_TRACKING_SERVER = -16,
	DF_OK_TRACKING_SENDING = 3,
	DF_ERROR_TRACKING_NODATA = -17,
	DF_ERROR_TRACKING_NOSESSION = -18,
	DF_ERROR_OUT_OF_MEMORY = -19,
	DF_ERROR_SOUND_ALREADY_INITIALIZED = -20,
	DF_ERROR_SOUND_UNKNOWN_TYPE = -21,
	DF_ERROR_INVALID_PROPERTY = -22,
	DF_ERROR_CANNOT_RELEASE_CREATIVE = -23,
	DF_ERROR_CREATIVE_WAS_RELEASED = -24,
	DF_ERROR_EXCEPTION = -25,
	DF_ERROR_ACTION_NOT_SUPPORTED = -26

} DFErrorCode;

#define DF_SUCCESS(x) ((x)>=0)
#define DF_FAIL(x) ((x)<0)

typedef unsigned int dfsize_t;

// memory alloc / free handlers prototypes
typedef void* (*DFMemoryAllocHandler)(dfsize_t);
typedef void (*DFMemoryFreeHandler)(void*);

#ifndef NULL
#define NULL 0
#endif

//////////////////////////////////////////////////////////////////
// Enums
//////////////////////////////////////////////////////////////////

// Double Fusion Object types
typedef enum 
{
	DFT_TEXTURE	= 0,
	DFT_3DMODEL	= 1,
	DFT_SOUND	= 2
}DFObjectType;

// Event types
typedef enum 
{
	DFE_VISIBLE		= 0,
	DFE_COLLISION	= 1,
	DFE_CLICK		= 2,
	DFE_PROXIMITY	= 3

}DFEventType;

typedef enum 
{      
      BGR		= 0,       
      BGRA		= 1,
      RGB        = 2,
      RGBA       = 3,
	  Custom     = 4
} DFBitmapFormat;

typedef enum
{
	DFS_DirectSound = 0
} DFSoundDeviceType;

typedef enum
{
	DFS_STATIC,
	DFS_PLAYING,
	DFS_STOPPED,
	DFS_FINISHED
} DFCreativeState;


typedef enum
{
	//  Property            // Expected type //
	///////////////////////////////////////////
	DFOP_LOOP = 0, 			// DF_UInt8 (0 / 1)
	DFOP_SOUND_VOLUME  = 1, // DF_UInt8 (0-100)
	DFOP_PLAY_STATE = 2  	// DFCreativeState
} DFObjectProperty;

typedef enum
{	// Action				// Description							// Required params
	// ======				// ===========							// ===============
	DFOA_START_MOVIE = 0,	// Start playing movie on next update() // NULL
	DFOA_PAUSE_MOVIE = 1,	// Stop playing movie					// NULL
	DFOA_RESET_MOVIE = 2	// Stops and rewinds movie				// NULL
} DFObjectAction;
//////////////////////////////////////////////////////////////////
// Data structures
//////////////////////////////////////////////////////////////////

// Visibility Event parameters
typedef struct DFEventVisibleParams
{
	DF_UInt32	m_visibleSize;
}DFEventVisibleParams;


#ifdef DF_WINDOWS
// image data
typedef struct DFImageData
{
	DF_UInt32 m_width;
	DF_UInt32 m_height;
	DF_UInt32 m_byteSize;	
	DF_UInt32 m_bytesPerPixel;
	DFBitmapFormat m_format;
	void* m_pBits;

	DF_UInt8 m_bFrameChanged;
}DFImageData;

#else

typedef struct DFImageData
{
	DF_UInt32 m_byteSize;	
	void* m_pBits;
} DFImageData;
#endif

typedef struct DFMemoryAllocator
{
	DFMemoryAllocHandler	fMemAllocHandler;
	DFMemoryFreeHandler		fMemFreeHandler;
	DFMemoryAllocHandler	fTempMemAllocHandler;
	DFMemoryFreeHandler		fTempMemFreeHandler;
} DFMemoryAllocator;

// creative info
typedef struct DFCreativeInfo
{
	const char* m_pUrl;
	const char* m_pName;
	const char* m_pText;
}DFCreativeInfo;

//////////////////////////////////////////////////////////

#ifdef _WIN32
// Used for dll exporting and importing
#define  DLL_EXPORT   extern "C" __declspec( dllexport ) 
#define  DLL_IMPORT   extern "C" __declspec( dllimport )

// Can't use extern "C" when DLL exporting a class
#define  DLL_CLASS_EXPORT   __declspec( dllexport ) 
#define  DLL_CLASS_IMPORT   __declspec( dllimport )

// Can't use extern "C" when DLL exporting a global
#define  DLL_GLOBAL_EXPORT   extern __declspec( dllexport ) 
#define  DLL_GLOBAL_IMPORT   extern __declspec( dllimport )
#elif (defined _LINUX || defined LINUX)

// Used for dll exporting and importing
#define  DLL_EXPORT   extern "C" 
#define  DLL_IMPORT   extern "C" 

// Can't use extern "C" when DLL exporting a class
#define  DLL_CLASS_EXPORT   
#define  DLL_CLASS_IMPORT  

// Can't use extern "C" when DLL exporting a global
#define  DLL_GLOBAL_EXPORT   extern
#define  DLL_GLOBAL_IMPORT   extern 

#elif defined PS2

// Used for dll exporting and importing
#define  DLL_EXPORT   extern "C" 
#define  DLL_IMPORT   extern "C" 

// Can't use extern "C" when DLL exporting a class
#define  DLL_CLASS_EXPORT   
#define  DLL_CLASS_IMPORT  

// Can't use extern "C" when DLL exporting a global
#define  DLL_GLOBAL_EXPORT   extern
#define  DLL_GLOBAL_IMPORT   extern 

#else
#error "Unsupported Platform."
#endif	


//////////////////////////////////////////////////////////////////
// SDK Version
//////////////////////////////////////////////////////////////////

#define MAJOR_VERSION	2
#define MINOR_VERSION	7

#define DF_ENGINE_SDK_VERSION	((   MAJOR_VERSION   <<24)+(MINOR_VERSION   <<16)+(0    <<8) + 0)

#endif /*DF_DONOT_DEFINE_TYPES*/

//////////////////////////////////////////////////////////////////
// Interfaces
//////////////////////////////////////////////////////////////////

/* ----------------------------------------------------------------------
 *  Define Classes with C and C++ versions
 *
 *  C++ version is default
 *  define DFENGINE_C_INTERFACE in include line to compile using C version
 * ---------------------------------------------------------------------- */

#ifndef DFENGINE_C_INTERFACE /* C++ interface */


#ifdef DFENGINE_EXPORTS
	#define DFENGINE_INTERFACE	DLL_EXPORT
#else
	#define DFENGINE_INTERFACE	DLL_IMPORT
#endif

///////////////////////////////////////////////////////////////////////////////
// Purpose: Interface to the DF Object
///////////////////////////////////////////////////////////////////////////////
class IDFObject
{
public:
	virtual DF_RESULT			GetAbsoluteLocalFileName(char*path, DF_UInt32 bufsize) = 0;
	virtual DF_RESULT			GetRelativeLocalFileName(char*path, DF_UInt32 bufsize) = 0;
	virtual void				UpdateOnEvent(DFEventType event, void* pEventData) = 0;
	virtual DF_RESULT			GetImageData(DFImageData* pImageData) = 0;
	virtual DF_RESULT			GetCreativeInfo(DFCreativeInfo* pCreativeInfo) = 0;
#ifdef DF_PS2
	virtual DF_RESULT			StartCreativeDownload(void) = 0;
	virtual DF_RESULT			ShutdownCreativeDownload(void) = 0;
	virtual DF_RESULT			CheckCreativeDownloadStatus(DF_RESULT* pStatus) = 0;
#endif

	virtual DF_RESULT			PerformAction(DFObjectAction action, void* params) = 0;
	virtual const char*			GetId(void) = 0;
	virtual DF_UInt32			GetInstanceId(void) = 0;
	virtual DFObjectType		GetType(void) const = 0;
	virtual const char*			GetName(void) = 0;
	virtual IDFObject*			CreateInstance(void) = 0;

	virtual DF_RESULT			ReleaseCurrentCreative (void) = 0;

	///////////////////////////////////////////////////////////////////////////////
	// Purpose: Refresh the creative selection for this object.
	// Input  : None.
	// Output : DF_OK if successful, any other result for error.
	//			Error can occur if default creative files are corrupted or 
	//			don't exist.
	///////////////////////////////////////////////////////////////////////////////
	virtual DF_RESULT			RefreshCurrentCreative(void) = 0;

	virtual DF_RESULT			SetProperty(DFObjectProperty prop, void* pValue) = 0;
	virtual DF_RESULT			GetProperty(DFObjectProperty prop, void* pValue) = 0;
};

///////////////////////////////////////////////////////////////////////////////
// Purpose: Interface to the DF engine
///////////////////////////////////////////////////////////////////////////////
class IDFEngine
{
public:
	///////////////////////////////////////////////////////////////////////////////
	// Purpose: Start the DoubleFusion Engine.
	// Input  : version - Should be DF_ENGINE_SDK_VERSION
	//			pRootDir - The path where all the df files are held.
	//			pMemoryAllocator - The memory handlers to use, or NULL for defaults.
	//			pGameId - For PS use only (Windows users should use NULL).
	//			pPlayerUniqueId - Unique ID of the player, if exists, or NULL otherwise.
	// Output : DF_OK if successful, any other result for error.
	///////////////////////////////////////////////////////////////////////////////
	virtual DF_RESULT	Start(DF_UInt32 version, const char* pRootDir, DFMemoryAllocator* pMemoryAllocator, const char* pGameId, const char* pPlayerUniqueId) = 0;

	virtual void		ShutDown(void) = 0;

	virtual DF_RESULT	SetSoundSystem(DFSoundDeviceType type, void* pDevice) = 0;

#ifdef DF_WINDOWS
	virtual DF_RESULT	CreateDFObject(const char* pObjectName, IDFObject** pDFObject) = 0;
#else
	virtual DF_RESULT	CreateDFObject(const char* pObjectName, const char* pObjectId, IDFObject** pDFObject) = 0;
#endif

	///////////////////////////////////////////////////////////////////////////////
	// Purpose: Destroy the given DF Object.
	// Input  : pDFObject - The object pointer to destroy.
	// Output : DF_OK if successful, any other result for error.
	///////////////////////////////////////////////////////////////////////////////
	virtual DF_RESULT	RemoveDFObject(IDFObject* pDFObject) = 0;

	///////////////////////////////////////////////////////////////////////////////
	// Purpose: Destroy all DF Objects in the given zone.
	// Input  : pZoneId - A zone name, i.e. "Zone1", or NULL for all objects.
	// Output : DF_OK if successful, any other result for error.
	///////////////////////////////////////////////////////////////////////////////
	virtual DF_RESULT	DestroyAllDfObjects(const char* pZoneId) = 0;

	///////////////////////////////////////////////////////////////////////////////
	// Purpose: Refresh the creative selection for all objects in zone.
	// Input  : pZoneId - A zone name, i.e. "Zone1", or NULL for all objects.
	// Output : DF_OK if successful, any other result for error.
	//			Error can occur if default creative files are corrupted or 
	//			don't exist.
	///////////////////////////////////////////////////////////////////////////////
	virtual DF_RESULT	RefreshCurrentCreatives(const char* pZoneId) = 0;

	virtual void		Update(float fTime) = 0;

	virtual DF_RESULT	StartZone(const char* pZoneId) = 0;

	virtual void		LeaveZone(const char* pZoneId) = 0;

	virtual DF_RESULT	UpdateContentFromServer(const char* pAdGroupId, float maxUpdateTime) = 0;

	virtual DF_RESULT	SetEngineParameter(const char* pParamName, const char* pParamValue) = 0;	

#ifndef DF_WINDOWS
	virtual DF_RESULT	LoginToServer(void) = 0;
	  virtual DF_RESULT CheckLoginStatus(DF_RESULT* pTrackingStatus) = 0;
	  virtual DF_RESULT	SendTrackingToServer(void) = 0;
	  virtual DF_RESULT CheckTrackingStatus(DF_RESULT* pTrackingStatus) = 0;
#endif
};

DFENGINE_INTERFACE IDFEngine* CreateDFEngine();

#else /* --------------- use C interface ------------------------- */

#ifdef __cplusplus
#ifdef DFENGINE_EXPORTS
	#define DFENGINE_INTERFACE	DLL_EXPORT
#else
	#define DFENGINE_INTERFACE	DLL_IMPORT
#endif
#else
#ifdef DFENGINE_EXPORTS
	#define DFENGINE_INTERFACE	DLL_GLOBAL_EXPORT
#else
	#define DFENGINE_INTERFACE	DLL_GLOBAL_IMPORT
#endif
#endif

/* IDFEngine wrappers */


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFEngine_Start
///
/// Start the Double Fusion Engine
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	DF_RESULT		DFEngine_Start(DF_UInt32 version, const char* pRootDir, DFMemoryAllocator* pMemoryAllocator, const char* pGameId, const char* pPlayerUniqueId);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFEngine_Shutdown
///
/// Shut down the Double Fusion Engine
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	void			DFEngine_Shutdown(void);


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFEngine_CreateDFObject
///
/// Create a new DF Object
/// Params:
/// 
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	DF_RESULT		DFEngine_CreateDFObject(const char* pName, const char* pId, lpDFObjectHandle pDFObject);

DFENGINE_INTERFACE	DF_RESULT		DFEngine_RemoveDFObject(DFObjectHandle pDFObject);

DFENGINE_INTERFACE	DF_RESULT		DFEngine_DestroyAllDfObjects(const char* pZoneId);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFEngine_Update
///
/// Update the state of the DF engine. Should be called ONCE each frame.
/// Params:  float fTime - elapsed time since the last frame in seconds (0.5 = 500 miliseconds)
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	void			DFEngine_Update(float fTime);

DFENGINE_INTERFACE	DF_RESULT		DFEngine_StartZone(const char* pZoneId);

DFENGINE_INTERFACE	void			DFEngine_LeaveZone(const char* pZoneId);

DFENGINE_INTERFACE	DF_RESULT		DFEngine_LoginToServer(void);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFEngine_CheckLoginStatus
///
/// Checks the status of login to the DF server
/// Params: Status is returned in PLoginStatus. The following values can be returned:
/// 	DF_ERROR_LOGIN_COMM - communication error
///	DF_ERROR_LOGIN_SERVER - communication succeeded but server returned an error
///	DF_OK_LOGGING_TO_SERVER - login in progress
///     DF_OK - logged in to server!
///     You can check the returned status using the DF_FAIL and DF_SUCCESS macros
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	DF_RESULT		DFEngine_CheckLoginStatus(DF_RESULT* pLoginStatus);

DFENGINE_INTERFACE	DF_RESULT		DFEngine_SendTrackingToServer(void);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFEngine_CheckTrackingStatus
///
/// Checks the status of sending tracking information to the server
/// Params: Status is returned in pTrackingStatus. The following values can be returned:
/// 	DF_ERROR_TRACKING_COMM - communication error
///	DF_ERROR_TRACKING_SERVER - communication succeeded but server returned an error
///	DF_OK_TRACKING_SENDING - sending tracking in progress
///     DF_OK - tracking info send successfully
///     You can check the returned status using the DF_FAIL and DF_SUCCESS macros
/// 
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	DF_RESULT		DFEngine_CheckTrackingStatus(DF_RESULT* pTrackingStatus);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// DFEngine_SetSoundSystem
/// 
/// Set the sound device used by the DFEngine.
/// Params: pDevice - the sound device pointer.
///			type - The type of the sound device.
///					Currently supported: DirectSound (DFS_DirectSound).
/// Return codes:
///		DF_ERROR_SOUND_UNKNOWN_TYPE - type given is unsupported.
///		DF_ERROR_SOUND_ALREADY_INITIALIZED - already initialized the sound system.
///		DF_ERROR - Failed to initialize the sound system.
///		DF_OK - Initialized the sound system successfully.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE  DF_RESULT		DFEngine_SetSoundSystem(DFSoundDeviceType type, void* pDevice)


/* IDFObject wrappers */

DFENGINE_INTERFACE      void*	DFObject_CreateInstance(void* pDFObject);

DFENGINE_INTERFACE	void			DFObject_UpdateOnEvent(DFObjectHandle pDFObject, DFEventType event, void* pEventData);

DFENGINE_INTERFACE	DF_RESULT		DFObject_StartCreativeDownload(DFObjectHandle pDFObject);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFObject_CheckCreativeDownloadStatus
///
/// Checks the status of creative download for a particular object
/// Params: Status is returned in pStatus. The following values can be returned:
/// 	DF_ERROR_CREATIVE_DL_COMM - communication error
///	DF_ERROR_CREATIVE_DL_SERVER - communication succeeded but server returned an error
///	DF_OK_CREATIVE_DOWNLOADING - downloading creative in progress
///     DF_OK - creative received successfully
///     You can check the returned status using the DF_FAIL and DF_SUCCESS macros
/// 
/// 
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	DF_RESULT		DFObject_CheckCreativeDownloadStatus(DFObjectHandle pDFObject, DF_RESULT* pStatus);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFObject_ShutdownCreativeDownload
///
/// Shut down the connection to the server. Also frees the memory used by the creative downloaded from the server.
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	DF_RESULT		DFObject_ShutdownCreativeDownload(DFObjectHandle pDFObject);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// DFObject_GetImageData
///
/// Get the creative data.This function should be called once the creative was successfuly downloaded from the server.
/// This function should be called BEFORE calling DFObject_ShutdownCreativeDownload since DFObject_ShutdownCreativeDownload
/// frees the image data
///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DFENGINE_INTERFACE	DF_RESULT		DFObject_GetImageData(DFObjectHandle pDFObject, DFImageData* pImageData);

DFENGINE_INTERFACE	const char*		DFObject_GetId(DFObjectHandle pDFObject);

DFENGINE_INTERFACE  const char*		DFObject_GetName(DFObjectHandle pDFObject);
	
DFENGINE_INTERFACE	DFObjectType	DFObject_GetType(DFObjectHandle pDFObject);

DFENGINE_INTERFACE	DF_RESULT		DFObject_PerformAction(DFObjectAction action, void* params, DFObjectHandle pDFObject);

DFENGINE_INTERFACE	DF_UInt32		DFObject_GetInstanceId(DFObjectHandle pDFObject);

DFENGINE_INTERFACE	DF_RESULT		DFObject_SetProperty(DFObjectHandle pDFObject, 
														 DFObjectProperty prop, 
														 void* pValue);

DFENGINE_INTERFACE	DF_RESULT		DFObject_GetProperty(DFObjectHandle pDFObject, 
														 DFObjectProperty prop, 
														 void* pValue);

DFENGINE_INTERFACE	DF_RESULT		DFObject_ReleaseCurrentCreative (DFObjectHandle pDFObject);

DFENGINE_INTERFACE	DF_RESULT		DFObject_RefreshCurrentCreative (DFObjectHandle pDFObject);

#endif /* C interface */


#endif /* _H_DFENGINEHEADER_H */
