// IcarusImplementation.h
#ifndef ICARUSIMPLEMENTATION_DEFINED
#define ICARUSIMPLEMENTATION_DEFINED

#ifndef ICARUSINTERFACE_DEFINED
#include "IcarusInterface.h"
#endif

#pragma warning( disable : 4786 )	// identifier was truncated 
#pragma warning (push, 3)			// go back down to 3 for the stl include
#pragma warning (disable:4503)		// decorated name length xceeded, name was truncated
#include <string>
#include <vector>
#include <map>
#include <list>
#include <algorithm>
#pragma warning (pop)
#pragma warning (disable:4503)		// decorated name length xceeded, name was truncated
using namespace std;


class CSequence;
class CSequencer;

class CIcarusSequencer;
class CIcarusSequence;

class CIcarus : public IIcarusInterface
{
public:
	CIcarus(int flavor);
	virtual ~CIcarus();

	inline IGameInterface* GetGame() {return IGameInterface::GetGame(m_flavor);};

	enum
	{
		MAX_STRING_SIZE			= 256,
		MAX_FILENAME_LENGTH		= 1024,
	};

protected:
	int						m_flavor;
	int						m_nextSequencerID;

	int						m_GUID;

	typedef list< CSequence * >				sequence_l;
	typedef list< CSequencer * >			sequencer_l;
	typedef map < int, CSequencer* >		sequencer_m;

	sequence_l				m_sequences;
	sequencer_l				m_sequencers;
	sequencer_m				m_sequencerMap;

	typedef map < string, unsigned char >	signal_m;
	signal_m				m_signals;

	static double ICARUS_VERSION;

#ifdef _DEBUG

	int	m_DEBUG_NumSequencerAlloc;
	int	m_DEBUG_NumSequencerFreed;
	int m_DEBUG_NumSequencerResidual;

	int	m_DEBUG_NumSequenceAlloc;
	int	m_DEBUG_NumSequenceFreed;
	int m_DEBUG_NumSequenceResidual;

#endif

public:
	static int				s_flavorsAvailable;
	static CIcarus**		s_instances;

	// mandatory overrides
	// Get the current Game flavor.
	int GetFlavor();

	int Save();
	int Load();
	int Run(int icarusID, char* buffer, long length);
	void DeleteIcarusID(int& icarusID);
	int GetIcarusID(int ownerID);
	int Update(int icarusID);

	int IsRunning(int icarusID);
	void Completed( int icarusID, int taskID );
	void Precache(char* buffer, long length);

protected:
	void Delete();
	void Free();

public:
	CSequence* GetSequence(int id);
	void DeleteSequence( CSequence *sequence );
	int AllocateSequences( int numSequences, int *idTable );
	CSequencer* FindSequencer(int sequencerID);
	CSequence* GetSequence();

protected:
	int SaveSequenceIDTable();
	int SaveSequences();
	int SaveSequencers();
	int SaveSignals();

	int LoadSignals();
	int LoadSequence();
	int LoadSequences();
	int LoadSequencers();

public:
	void Signal( const char *identifier );
	bool CheckSignal( const char *identifier );
	void ClearSignal( const char *identifier );

	// Overloaded new operator.
	inline void *operator new( size_t size )
	{
		return IGameInterface::GetGame()->Malloc( size );
	}

	// Overloaded delete operator.
	inline void operator delete( void *pRawData )
	{
		// Free the Memory.
		IGameInterface::GetGame()->Free( pRawData );
	}

public:
	enum 
	{
		TK_EOF = -1,
		TK_UNDEFINED,
		TK_COMMENT,
		TK_EOL,
		TK_CHAR,
		TK_STRING,
		TK_INT,
		TK_INTEGER = TK_INT,
		TK_FLOAT,
		TK_IDENTIFIER,
		TK_USERDEF,
		TK_BLOCK_START = TK_USERDEF,
		TK_BLOCK_END,
		TK_VECTOR_START,
		TK_VECTOR_END,
		TK_OPEN_PARENTHESIS,
		TK_CLOSED_PARENTHESIS,
		TK_VECTOR,
		TK_GREATER_THAN,
		TK_LESS_THAN,
		TK_EQUALS,
		TK_NOT,

		NUM_USER_TOKENS
	};

	//ID defines
	enum
	{
		ID_AFFECT = NUM_USER_TOKENS,
		ID_SOUND,
		ID_MOVE,
		ID_ROTATE,
		ID_WAIT,
		ID_BLOCK_START,
		ID_BLOCK_END,
		ID_SET,
		ID_LOOP,
		ID_LOOPEND,
		ID_PRINT,
		ID_USE,
		ID_FLUSH,
		ID_RUN,
		ID_KILL,
		ID_REMOVE,
		ID_CAMERA,
		ID_GET,
		ID_RANDOM,
		ID_IF,
		ID_ELSE,
		ID_REM,
		ID_TASK,
		ID_DO,
		ID_DECLARE,
		ID_FREE,
		ID_DOWAIT,
		ID_SIGNAL,
		ID_WAITSIGNAL,
		ID_PLAY,

		ID_TAG,
		ID_EOF,
		NUM_IDS
	};

	//Type defines
	enum
	{
		//Wait types
		TYPE_WAIT_COMPLETE	 = NUM_IDS,
		TYPE_WAIT_TRIGGERED,

		//Set types
		TYPE_ANGLES,
		TYPE_ORIGIN,

		//Affect types
		TYPE_INSERT,	
		TYPE_FLUSH,	
		
		//Camera types
		TYPE_PAN,
		TYPE_ZOOM,
		TYPE_MOVE,
		TYPE_FADE,
		TYPE_PATH,
		TYPE_ENABLE,
		TYPE_DISABLE,
		TYPE_SHAKE,
		TYPE_ROLL,
		TYPE_TRACK,
		TYPE_DISTANCE,
		TYPE_FOLLOW,
			
		//Variable type
		TYPE_VARIABLE,

		TYPE_EOF,
		NUM_TYPES
	};

	// Used by the new Icarus Save code.
	enum { MAX_BUFFER_SIZE = 100000 };
	unsigned long m_ulBufferCurPos;
	unsigned long m_ulBytesRead;
	unsigned char *m_byBuffer;
	// Destroy the File Buffer.
	void DestroyBuffer();
	// Create the File Buffer.
	void CreateBuffer();
	// Reset the buffer completely.
	void ResetBuffer();
	// Write to a buffer.
	void BufferWrite( void *pSrcData, unsigned long ulNumBytesToWrite );
	// Read from a buffer.
	void BufferRead( void *pDstBuff, unsigned long ulNumBytesToRead );
};

#endif