#ifndef __XENTAX_BONE_H
#define __XENTAX_BONE_H

#define INVALID_JOINT 0xFFFFFFFF

struct JOINT {
 std::string name;
 uint32 parent;
 boost::shared_array<float> matrix;
 float rel_x;
 float rel_y;
 float rel_z;
};

struct JOINTTREENODE {
 typedef std::deque<uint32> list_t;
 JOINT joint;
 list_t children;
};

class JOINTTREE {
 public :
  typedef JOINTTREENODE node_t;
  typedef std::map<uint32, JOINTTREENODE> tree_t;
  typedef tree_t::iterator tree_iterator;
  typedef tree_t::const_iterator const_tree_iterator;
 private :
  uint32 root;
  tree_t tree;
 public :
  bool InsertJoint(uint32 index, const JOINT& joint);
  bool RemoveJoint(uint32 index);
 public :
  void PrintJointTree(std::stringstream& ss)const;
  void PrintJointTree(std::stringstream& ss, uint32 index, uint32 level)const;
  void PrintColladaNodeHeirarchy(const std::string& id, std::stringstream& ss)const;
  void PrintColladaNodeHeirarchy(const std::string& id, std::stringstream& ss, uint32 index, uint32 level)const;
  void PrintColladaJoints(const std::string& id, std::stringstream& ss)const;
  void PrintColladaJoints(std::stringstream& ss, uint32 index)const;
  void PrintColladaBindMatrices(const std::string& id, std::stringstream& ss)const;
  void PrintColladaBindMatrices(std::stringstream& ss, uint32 index)const;
 public :
  JOINTTREE();
};

/*

template<class T>
void AbsoluteToRelativeJointList(JOINTLIST<T>& jl, const JOINTTREE<T>& jt, const T& node)
{
 // visit children of joint tree node
 JOINTTREE<T>::const_iterator jt_iter = jt.data.find(node);
 if(jt_iter == jt.data.end()) return;
 for(size_t i = 0; i < jt_iter->second.size(); i++) AbsoluteToRelativeJointList(jl, jt, jt_iter->second[i]);

 // obtain pointers to joints
 JOINTLIST<T>::const_iterator jl_citer = jl.data.find(node);
 JOINTLIST<T>::const_iterator jl_piter = jl.data.find(jl_citer->second.parent);
 if(jl_piter == jl.data.end()) return;

 // modify matrix
 jl_citer->second.matrix[ 3] = jl_piter->second.matrix[ 3] - jl_citer->second.matrix[ 3];
 jl_citer->second.matrix[ 7] = jl_piter->second.matrix[ 7] - jl_citer->second.matrix[ 7];
 jl_citer->second.matrix[11] = jl_piter->second.matrix[11] - jl_citer->second.matrix[11];
}

template<class T>
void AbsoluteToRelativeJointList(JOINTLIST<T>& jl, const JOINTTREE<T>& jt)
{
 JOINTTREE<T>::const_iterator iter = jt.data.find(jt.root);
 if(iter == jt.data.end()) return;
 AbsoluteToRelativeJointList(jl, jt, iter->first);
}

template<class T>
void PrintDAEJointTree(const JOINTLIST<T>& jl, const JOINTTREE<T>& jt, const T& node, uint32 level, std::stringstream& ss)
{
 // determine spacing
 std::string spacing = "";
 for(size_t i = 0; i < level; i++) spacing += ' ';

 // begin node
 JOINTLIST<T>::const_iterator jl_iter = jl.data.find(node);
 if(jl_iter == jl.data.end()) return;
 ss << "   " << spacing << "<node name=\"" << jl_iter->second.name << "\" id=\"" << jl_iter->second.name << "\" type=\"JOINT\">" << std::endl;

 // print matrix
 boost::shared_array<float> m = jl_iter->second.matrix;
 ss << "   " << spacing << " <matrix>" << std::endl;
 ss << "   " << spacing << "  " << m[ 0] << " " << m[ 1] << " " << m[ 2] << " " << m[ 3] << std::endl;
 ss << "   " << spacing << "  " << m[ 4] << " " << m[ 5] << " " << m[ 6] << " " << m[ 7] << std::endl;
 ss << "   " << spacing << "  " << m[ 8] << " " << m[ 9] << " " << m[10] << " " << m[11] << std::endl;
 ss << "   " << spacing << "  " << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << std::endl;
 ss << "   " << spacing << " </matrix>" << std::endl;

 // visit children of joint tree node
 JOINTTREE<T>::const_iterator jt_iter = jt.data.find(node);
 if(jt_iter == jt.data.end()) return;
 for(size_t i = 0; i < jt_iter->second.size(); i++) PrintDAEJointTree(jl, jt, jt_iter->second[i], level + 1, ss);

 // end node
 ss << "   " << spacing << "</node>" << std::endl;
}

template<class T>
void PrintDAEJointTree(const JOINTLIST<T>& jl, const JOINTTREE<T>& jt, std::stringstream& ss)
{
 JOINTTREE<T>::const_iterator iter = jt.data.find(jt.root);
 if(iter == jt.data.end()) return;
 uint32 level = 0;
 PrintDAEJointTree(jl, jt, iter->first, level, ss);
}

*/

#endif
