#ifdef ASURA_USE_AXON
//////////////////////////////////////////////////////////////////////////////
//
// Axon_Behaviour.h
//
// Created by NJD - 17 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_BEHAVIOUR_H__
#define __AXON_BEHAVIOUR_H__ 1

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

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

class Asura_Chunk_Stream;
class Asura_Message;
class Axon_BehaviourParams;
class Axon_Brain;
class Tools_EntityTemplateInstance;

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Behaviour
//
// A note on behaviours:
// Behaviours have a type (what type of behaviour they are) and an ID, which is unique for every behaviour.
// IDs are useful if there is to be more than one of a particular behaviour type in a hierarchy. In this case
// getting or unlinking by type is not safe.
//
// During activation Activate is called on each behaviour and then on that behaviour's children, and so on
// down the hierarchy. During deactivation Deactivate is called first on the very lowest children and then
// on their parent, and so on up the hierarchy.
//
// Behaviours are in charge of their children (via the child pointer and its sibling pointer linked list).
// Behaviours should not switch between children by keeping them around and pausing/unpausing them,
// they should create and destroy children as needed.
//
// The correct order for creation is:
// - Create behaviour.      // Axon_Behaviour* pxBehaviour = m_pxBrain->CreateBehaviour( SOME_BEHAVIOUR_TYPE );
// - Activate behaviour.    // pxBehaviour->DoActivate();
// - Link behaviour.        // LinkChild( pxBehaviour );
//
// The correct order for destruction is:
// - Unlink behaviour.      // Axon_Behaviour* pxBehaviour = UnlinkChildWithType( this, SOME_BEHAVIOUR_TYPE );
// - Deactivate behaviour.  // pxBehaviour->DoDeactivate();
// - Destroy behaviour.     // m_pxBrain->DestroyBehaviour( pxBehaviour );
//
// If a behaviour requires a child from the very beginning of operation is it best to create this child at
// activation time. Failure to create the child can be reported then by returning false. Note that at this
// time it is only necessary to link the child, not activate it explicitly, as it will be activated immediately
// after its parent automatically. There is no harm in activating immediately if desired.
//
// Pause and Unpause are intended to operate on the whole behaviour hierarchy, and are for use
// when either a new hierarchy is pushed on top of an existing hieararchy on the stack, or the brain as
// a whole is paused.
//
// When a brain is saved only the top behaviour, at each level of the stack, is saved.
// It is the job of these top behaviours to decide what details about their children to save. They are then
// responsible for reinstating the behaviour hierarchy after a load.
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Behaviour
{
public:
    Axon_Behaviour( const u_int uBehaviourType, Axon_Brain* pxBrain );
	virtual ~Axon_Behaviour() {}

    // Only the top behaviours and their siblings are saved/loaded. They then decide what data, if any, of their children to save.
    virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream );
    virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;

    bool DoHandleMessage( const Asura_Message* pxMessage, const bool bAlwaysHandle = false );
	void DoHandleParams( const Axon_BehaviourParams* pxParams );
    bool DoActivate();
    void DoDeactivate();
    void DoPause();
    void DoUnpause();
	void DoPostLoadInitialise();
	void DoPerFrameUpdate( const float fTimeslice );
    void DoUpdate( const float fTimeslice );
#ifndef ASURA_NO_DEBUG_OUTPUT
    void DoRenderDebugInfo();
#endif
#ifdef ASURA_TOOLS
    void DoApplyChangesForTemplateInstance( Tools_EntityTemplateInstance* pxInstance );
#endif

	Axon_Behaviour* CreateChildWithType( const u_int uChildType, const Asura_Message* pxMessage = NULL, const bool bIncludeActivation = true );
	// The child will normally need to be deactivated before being destroyed. The exception to this is in the Deactivate functions of behaviours,
	// where the children will already have been deactivated, so will assert if deactivated again.
	void			DestroyChildWithType( const u_int uChildType, const bool bIncludeDeactivation = true, const bool bFullTreeSearch = false );
	void			DestroyAllChildren( const bool bIncludeDeactivation = true );

    void LinkChild( Axon_Behaviour* pxChildBehaviour );
    void LinkSibling( Axon_Behaviour* pxSiblingBehaviour );
    void SetStackChild( Axon_Behaviour* pxBehaviour ) { m_pxStackChild = pxBehaviour; }

    // Various methods to get children and siblings.
    // Note the important difference between getting by type and by ID. All behaviours have a unique ID, but behaviours can be of the same type.
    // GetChildByID searches the full tree automatically, as it's assumed the user knows which behaviour ID they're interested in.
    // GetChildByType requires a start behaviour (which will usually be the searching behaviour), to avoid problems when faced
    // with more than one behaviour of the same type in the same hierarchy.
    Axon_Behaviour* GetSibling()    const { return m_pxSibling; }
    Axon_Behaviour* GetChild()      const { return m_pxChild; }
    Axon_Behaviour* GetStackChild() const { return m_pxStackChild; }
    Axon_Behaviour* GetSiblingWithID( const u_int uBehaviourID ) const;
    Axon_Behaviour* GetChildWithID( const u_int uBehaviourID ) const;
    Axon_Behaviour* GetSiblingWithType( const u_int uBehaviourType ) const;
    Axon_Behaviour* GetChildWithType( const Axon_Behaviour* pxStartBehaviour, const u_int uBehaviourType, const bool bFullTreeSearch = false ) const;

    // Various methods to unlink and optionally get children and siblings.
    // The same comments apply as apply to the 'get' methods above.
	bool            UnlinkSibling( Axon_Behaviour* pxSiblingBehaviour );
    bool            UnlinkChild( Axon_Behaviour* pxChildBehaviour );
	Axon_Behaviour* UnlinkSiblingWithID( const u_int uBehaviourID );
	Axon_Behaviour* UnlinkChildWithID( const u_int uBehaviourID );
    Axon_Behaviour* UnlinkSiblingWithType( const u_int uBehaviourType );
    Axon_Behaviour* UnlinkChildWithType( Axon_Behaviour* pxStartBehaviour, const u_int uBehaviourType, const bool bFullTreeSearch = false );

	Axon_Brain* GetBrain()				const { return m_pxBrain; }
    u_int		GetID()					const { return m_uID; }
    u_int		GetType()				const { return m_uType; }
    bool		IsPaused()				const { return m_bIsPaused; }
    bool		IsFinished()			const { return m_bIsFinished; }
    bool		IsInError()				const { return m_bIsInError; }
	// (TI - 04.06.2007) - Note that this is set to true even if Activate() fails 
	// so this is NOT to be used to test if the behaviour is active or not.
	bool		HasActivateBeenCalled() const { return m_bActivateCalled; }

    void SetFinished( const bool bFinished = true ) { m_bIsFinished = bFinished; }
    void SetInError( const bool bInError = true )   { m_bIsInError  = bInError; }

protected:
    // Returns whether the message was handled or not.
    virtual bool HandleMessage( const Asura_Message* pxMessage ) { return false; }
	virtual void HandleParams( const Axon_BehaviourParams* pxParams ) {}
    // Establish the behaviour state for the first time. Note that if activation fails, deactivate is not called.
    virtual bool Activate() { return true; }
    // Exit from the behaviour and release any resources.
    virtual void Deactivate() {}
    // Pause the behaviour ready for resumption at a later time.
    virtual void Pause() {}
    // Resume the behaviour from its previously paused state. See above note on Unpause being called on Brain shutdown.
    virtual void Unpause() {}
	// Called after all resources have been loaded and before the game begins.
	virtual void PostLoadInitialise() {}
	// This update is called every frame. To be used only if needed.
	virtual void PerFrameUpdate( const float fTimeslice ) {}
    // Updates the behaviour.
    virtual void Update( const float fTimeslice ) {}
#ifndef ASURA_NO_DEBUG_OUTPUT
	// Render anything useful for debugging to screen.
    virtual void RenderDebugInfo() {}
#endif
#ifdef ASURA_TOOLS
    virtual void ApplyChangesForTemplateInstance( Tools_EntityTemplateInstance* pxInstance ) {}
#endif

private:
	const u_int m_uID;
	Axon_Brain* m_pxBrain;
    union
    {
        u_int m_uBehaviourFlags;
        struct
        {
            u_int m_bActivateCalled   : 1,
                  m_bIsPaused         : 1,
                  m_bIsFinished       : 1,
                  m_bIsInError        : 1;
        };
    };
    const u_int     m_uType;
    Axon_Behaviour* m_pxSibling;
    Axon_Behaviour* m_pxChild;
    Axon_Behaviour* m_pxStackChild;

private:
    enum { CURRENT_CHUNK_VERSION = 3 };
};

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

#endif //__AXON_BEHAVIOUR_H__
#endif
