//////////////////////////////////////////////////////////////////////////////
//
// Axon_Project_Brain.h
//
// Created by NJD - 24 August 2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
#pragma once
#endif

#ifndef __AXON_PROJECT_BRAIN_H__
#define __AXON_PROJECT_BRAIN_H__ 1

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

// asura
#include "Core/Asura_Maths.h"
#include "Network/Asura_Guid.h"

// axon
#include "Core/Axon_Brain.h"

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

class Asura_Mempool;
class Asura_Message;
class Axon_Behaviour;

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Project_Brain
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Project_Brain : public Axon_Brain
{
    typedef Axon_Brain PARENT;
    friend class ToolsAVP_Entity_Actor;

public:
    Axon_Project_Brain( Asura_Guid uOwnerGuid );

	virtual void DoPerFrameUpdate( const float fTimeslice );

    virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream );
    virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;

    virtual void DestroyBehaviour( Axon_Behaviour*& pxBehaviour );
	
#ifndef ASURA_NO_DEBUG_OUTPUT
    Asura_Vector_2& GetDebugOutputPos() { return m_xDebugOutputPos; }
#endif

    static u_int GetLargestBehaviourSize();
    static void  InitialiseBehaviourMempool();
    static void  ShutdownBehaviourMempool();

	static bool IsProjectBehaviourType( const Axon_Behaviour* pxBehaviour );

#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
	static bool s_bRenderAIDebugInfo;
#endif

protected:
#ifndef ASURA_NO_DEBUG_OUTPUT
	bool VerifyFailed() const { return m_bVerifyFailed; }
	virtual bool Verify();
#endif
	virtual void UpdateBehaviours( const float fTimeslice );
#ifndef ASURA_NO_DEBUG_OUTPUT
	static void OutputBehaviourMempoolContents();
#endif

protected:
#ifndef ASURA_NO_DEBUG_OUTPUT
    Asura_Vector_2 m_xDebugOutputPos;
#endif

	static Asura_Mempool* s_pxBehaviourMempool;

#ifndef ASURA_NO_DEBUG_OUTPUT
private:
	bool m_bVerifyFailed;
#endif

private:
    enum { CURRENT_CHUNK_VERSION = 0 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Experimental templatised helpers.
//
//////////////////////////////////////////////////////////////////////////////

template< typename EntryType, typename CompType > struct AVP_MinCalculator
{
	AVP_MinCalculator( const EntryType& xEntry, const CompType& xComp ) : m_xEntry( xEntry ), m_xMinComp( xComp ) {}

	void Initialise( const EntryType& xEntry, const CompType& xComp ) { m_xEntry = xEntry; m_xMinComp = xComp; }
	void UpdateMin( const EntryType& xEntry, const CompType& xComp )
	{
		if ( xComp < m_xMinComp )
		{
			m_xEntry   = xEntry;
			m_xMinComp = xComp;
		}
	}
	const EntryType& GetMinEntry() const { return m_xEntry; }
	const CompType&  GetMinComp()  const { return m_xMinComp; }

	EntryType m_xEntry;
	CompType  m_xMinComp;
};

template< typename EntryType, typename CompType > struct AVP_MaxCalculator
{
	AVP_MaxCalculator( const EntryType& xEntry, const CompType& xComp ) : m_xEntry( xEntry ), m_xMaxComp( xComp ) {}

	void Initialise( const EntryType& xEntry, const CompType& xComp ) { m_xEntry = xEntry; m_xMaxComp = xComp; }
	void UpdateMax( const EntryType& xEntry, const CompType& xComp )
	{
		if ( xComp > m_xMaxComp )
		{
			m_xEntry   = xEntry;
			m_xMaxComp = xComp;
		}
	}
	const EntryType& GetMax() const { return m_xEntry; }

	EntryType m_xEntry;
	CompType  m_xMaxComp;
};

template< typename FlagFieldType, typename FlagValueType >
static bool AVP_FlagIsSet( const FlagFieldType& xFlagField, const FlagValueType& xFlagValueToTest )
{
	return ( ( xFlagField & xFlagValueToTest ) != 0 );
}

template< typename FlagFieldType, typename FlagValueType >
static void AVP_SetFlag( FlagFieldType& xFlagField, const FlagValueType& xFlagValueToSet )
{
	xFlagField |= xFlagValueToSet;
}

template< typename FlagFieldType, typename FlagValueType >
static void AVP_ClearFlag( FlagFieldType& xFlagField, const FlagValueType& xFlagValueToClear )
{
	xFlagField &= ~xFlagValueToClear;
}

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

#endif //__AXON_PROJECT_BRAIN_H__
