#ifndef __AIHPP__
#define __AIHPP__

#pragma warning (disable:4291)

#include <windows.h>
#include <utils\utils.h>

class AI;

enum AIAREA { COMBAT_AREA, BARGAIN_AREA, CONVERSATION_AREA,
		COMMUNICATION_AREA, AWARE_AREA, PLAYER_AREA, MOVE_AREA, MAX_AIAREA};


#include "ai command.hpp"

#include "ai nnet.hpp"
#include "ai priority.hpp"
#include "ai aware.hpp"
#include "ai combat.hpp"
#include "ai comm.hpp"
#include "ai conversation.hpp"
#include "ai move.hpp"

#define SORT_DEPTH 4

void InitAI (bool firstpass);
void KillAI (void);

class AI
{
friend class AIAwareness;
friend class AICombat;
friend class AIConverse;
friend class AIComm;
friend class AIMove;

protected:
	enum SORTTYPE {SORT_NULL,SORT_PRIORITY,SORT_VALID,SORT_AREA};

private:
	CommandEntry *m_RootCommand,*m_SortRoot;
	SORTTYPE m_LastSort[SORT_DEPTH];
	UINT m_AreaOrder[MAX_AIAREA];

#ifdef _DEBUG
	bool CheckCommandValid (CommandEntry *cmd);
#else
	bool CheckCommandValid (CommandEntry *cmd) {return true;}
#endif

protected:
	CPoint m_Location;

	CString m_Name;
	AIAwareness *m_Awareness;
	AICombat *m_Combat;
	AIConverse *m_Converse;
	AIComm *m_Comm;
	AIMove *m_Move;

	CommandEntry *m_AreaLastCommand[MAX_AIAREA];

	void SetAreaOrder (const UINT neworder[MAX_AIAREA],bool resort = true);
	int CompareArea (AIAREA c1,AIAREA c2) const
	{
		return m_AreaOrder[c1] - m_AreaOrder[c2];
	}


	void SortCommandList (const SORTTYPE on[SORT_DEPTH]);
	void InsertCommand (CommandEntry *cmd);
	CommandEntry *GetTopCommand (bool sorted=false) const
	{
		return sorted ? m_SortRoot : m_RootCommand;
	}
	void RemoveCommand (CommandEntry *cmd);
	CommandEntry *GetNextCommand (CommandEntry *cmd,bool sorted=false) const
	{
		assert (cmd);
		if (sorted)
			return cmd->sort_next;
		return cmd->next;
	}
	void ExecuteCommand (CommandEntry *command);

public:
	AI (void);
	~AI (void);

	bool Think (double value);
	const CPoint& Location (void) { return m_Location; }
	AIAwareness *Awareness (void) { return m_Awareness; }
	AICombat *Combat (void) { return m_Combat; }
	AIConverse *Converse (void) { return m_Converse; }
	AIComm *Comm (void) { return m_Comm; }
	AIMove *Move (void) { return m_Move; }
};

#endif