/**
* Bone Record System
* @version: 03-02-2005
* @author Joseph 'Pcjoe' Florencio
*/

#ifndef BONEREC_H
#define BONEREC_H

#include "quaternion.h"

/*
* Bone Data Class
*/
class CBoneData
{
public:
	CBoneData() { }

	// Set position and rotation from bones matrix data
	void setFromMatrix( float matrix[3][4] );

	/*
	* Accessors
	*/
	// Name
	void setName( std::string strName ) { m_strName = strName; }
	std::string getName( void ) { return m_strName; }

	// Position
	void setPosition( vec3_t vecPosition ) { m_vecPosition = vecPosition; }
	vec3_t getPosition( void ) { return m_vecPosition; }

	// Rotation
	CQuaternion *getRotation( void ) { return (&m_qRotation); }

private:
	std::string m_strName;
	vec3_t		m_vecPosition;
	CQuaternion	m_qRotation;
};

/*
* Bone Accessor Class
*/
class CBoneAccessor
{
public:
	// Constructor
	CBoneAccessor() { setEntIndex(0); setDependencies(0); setValidData(false); setTempEntity(NULL); }

	// Get Studio Header
	studiohdr_t *getStudioHeader( void );

	// Check model (call updateInitialInfo if model name changes)
	void checkModel( void );

	// Update initial information ( bone names ), must set ent index prior to calling this
	void updateInitialInfo( void );

	// Update attachments
	void updateAttachments( void );

	// Set bone data from bone transform array
	void setBoneData( float (*pBoneTransform)[MAXSTUDIOBONES][3][4] );

	// Set render data ( render position + angle )
	void setRenderData( float (*pRotationMatrix)[3][4], vec3_t vecAng );

	// Get bone
	CBoneData *getBone( int iBone );
	CBoneData *getBone( std::string name );

	// DEBUG: print bone data
	void printData( void );

	/*
	* Accessors
	*/
	// Entity Index
	void setEntIndex( int idx ) { m_iEntIndex = idx; }
	int getEntIndex( void ) { return m_iEntIndex; }

	// Model name
	void setModel( std::string strModel ) { m_strModel = strModel; }
	std::string getModel( void ) { return m_strModel; }

	// Dependencies (how many things are depending on this bone data?)
	void setDependencies( int iDep ) { m_iDependencies = iDep; }
	int getDependencies( void ) { return m_iDependencies; }
	void incDependencies( void ) { setDependencies( getDependencies()+1 ); }
	void decDependencies( void ) { setDependencies( getDependencies()-1 ); }

	// Has data (has bone data been updated to this accessor yet?)
	void setValidData( bool data ) { m_bHasValidData = data; }
	bool hasValidData( void ) { return m_bHasValidData; }

	// Render Position
	void setRenderPosition( vec3_t vecPos ) { m_vecRenderPosition = vecPos; }
	vec3_t getRenderPosition( void ) { return m_vecRenderPosition; }

	// Render Angle
	void setRenderAngle( vec3_t vecAng ) { m_vecRenderAngle = vecAng; }
	vec3_t getRenderAngle( void ) { return m_vecRenderAngle; }

	// Temp Entity
	void setTempEntity( cl_entity_t *pEnt ) { m_pTempEntity = pEnt; }
	cl_entity_t *getTempEntity( void ) { return m_pTempEntity; }

	// Bone Data
	std::vector<CBoneData> *getBoneData( void ) { return (&m_BoneData); }

	// Attachments
	std::vector<vec3_t> *getAttachments( void ) { return (&m_Attachments); }
private:
	std::vector<CBoneData>	m_BoneData;
	std::vector<vec3_t>		m_Attachments;
	std::string				m_strModel;
	vec3_t					m_vecRenderAngle;
	vec3_t					m_vecRenderPosition;
	cl_entity_t				*m_pTempEntity;
	int	m_iEntIndex;
	int	m_iDependencies;
	bool m_bHasValidData;
};

/*
* Bone Manager Class
*/
class CBoneManager
{
public:
	CBoneManager();

	// Add Accessor
	CBoneAccessor *addAccessor( int idx );

	// Remove Accessor
	void removeAccessor( int idx );
	void removeAccessor( CBoneAccessor *pBoneAccessor );

	// Find Accessor
	CBoneAccessor *findAccessor( int idx );

	/*
	* Accessors
	*/
	// Bone Accessors
	std::list<CBoneAccessor> *getBoneAccessors( void ) { return (&m_BoneAccessors); }
private:
	std::list<CBoneAccessor> m_BoneAccessors;
};

extern CBoneManager gBoneManager;

#endif