#ifdef ASURA_USE_AXON
//////////////////////////////////////////////////////////////////////////////
//
// Axon_Knowledge_System.h
//
// Created by NJD - 29 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_KNOWLEDGE_SYSTEM_H__
#define __AXON_KNOWLEDGE_SYSTEM_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_Mempool.h"
#include "Debugging/Asura_Assert.h"

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

class Asura_Blueprint;
class Asura_Chunk_Stream;
class Asura_Message;

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Knowledge_System
//
//////////////////////////////////////////////////////////////////////////////

static const u_int AXON_INVALID_KNOWLEDGE_ID = 0;

template < class KnowledgeType >
class Axon_Knowledge_System
{
public:
	Axon_Knowledge_System() {}
    virtual ~Axon_Knowledge_System() {}

    static void CreateStorage()
    {
        if ( !s_pxKnowledgeMempool )
        {
            s_pxKnowledgeMempool = new Asura_ResizingMempool( s_iMempoolPageSize, sizeof( KnowledgeType ), __FILE__, __LINE__ );
        }
    }
    static void DestroyStorage()
    {
        if ( s_pxKnowledgeMempool )
        {
            delete s_pxKnowledgeMempool;
            s_pxKnowledgeMempool = NULL;
        }
    }
	static void ResetStorage()
	{
		if (s_pxKnowledgeMempool)
		{
			s_pxKnowledgeMempool->Reset();
		}
	}

    virtual void InitialiseFromBlueprint( const Asura_Blueprint& xBlueprint ) {}
    virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream )      = 0;
    virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const = 0;
    virtual void Initialise()                     {}
    virtual void Update( const float fTimeslice ) {}
    virtual void Shutdown()                       {}
    virtual bool HandleMessage( const Asura_Message* pxMessage ) { return false; }
#ifndef ASURA_NO_DEBUG_OUTPUT
    virtual void RenderDebugInfo() {}
#endif

	KnowledgeType* CreateKnowledge();
	void DestroyKnowledge( KnowledgeType*& pxKnowledge );

	unsigned int GetNewKnowledgeID() { return ++s_uCurrentKnowledgeID; }

    static void  SetMempoolPageSize( const int i ) { s_iMempoolPageSize = i; }

protected:
    static int                          s_iMempoolPageSize;
    static class Asura_ResizingMempool* s_pxKnowledgeMempool;
	static unsigned int                 s_uCurrentKnowledgeID;
};

template < class KnowledgeType > int                    Axon_Knowledge_System< KnowledgeType >::s_iMempoolPageSize    = 8;
template < class KnowledgeType > Asura_ResizingMempool* Axon_Knowledge_System< KnowledgeType >::s_pxKnowledgeMempool  = NULL;
template < class KnowledgeType > unsigned int           Axon_Knowledge_System< KnowledgeType >::s_uCurrentKnowledgeID = AXON_INVALID_KNOWLEDGE_ID;


#include "Core/Asura_MemoryManagement_DebugOff.h"
template < class KnowledgeType >
KnowledgeType* Axon_Knowledge_System< KnowledgeType >::CreateKnowledge()
{
	void* pMemory = s_pxKnowledgeMempool->Allocate();
	if ( pMemory )
	{
		return new( pMemory ) KnowledgeType;
	}
	else
	{
		return NULL;
	}
}
#include "Core/Asura_MemoryManagement_DebugOn.h"
template < class KnowledgeType >
void Axon_Knowledge_System< KnowledgeType >::DestroyKnowledge( KnowledgeType*& pxKnowledge )
{
	pxKnowledge->~KnowledgeType();
	s_pxKnowledgeMempool->Deallocate( pxKnowledge );
	pxKnowledge = NULL;
}

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

#endif //__AXON_KNOWLEDGE_SYSTEM_H__
#endif
