///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (C) 2006 by Intel Corporation and Carnegie Mellon University    //
// Contacts: casey.j.helfrich @ intel.com                                    //
//           bdr @ cs.cmu.edu                                                //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#ifndef __CATOMSIM_HXX
#define __CATOMSIM_HXX

#include <sstream>
#include <vector>
#include <pthread.h>
#include <errno.h>
#include <string.h>

#include "StateFile/BasicTypes.hxx"
#include "StateFile/StateFile.hxx"
#include "Catom.hxx"
#include <ode/ode.h>

using namespace std;

extern vector<pthread_t> catomThreadList;
extern pthread_key_t _tcatom;
extern pthread_key_t _tcatomsim;
#define thisCatom() ((Catom*)(pthread_getspecific(_tcatom)))
#define thisCatomSim() ((CatomSim*)(pthread_getspecific(_tcatomsim)))

///////////////////////////////////////////////////////////////////////////////
// CatomSim
//
// The CatomSim wrapper class contains extra data for the simulation that is
// never known by any real catom.
//

class CatomSim {
public:
  // The "Real" Catom
  Catom C;

  // Loaded code modules
  vector<CodeModule*> codeModules;
  
  // Physics stuff
  dBodyID body;
  dGeomID shape;
  dGeomID shape2;
  dGeomID *feature_points;
  dSpaceID feature_container;
  static dMass* catom_mass_ptr;
  static dMass catom_mass_struct;
  static double catom_mass;
  static double catom_radius;
  static double magnet_depth;
  static double magnet_max_force;
  static double magnet_radius;
  Point3D magic_force;
  Point3D magic_torque;
  char *magnet_state;

  // Proximal catoms list
  set<CatomSim*> nearCatoms;

  // Visualization information
  uint8 red;
  uint8 green;
  uint8 blue;
  uint8 alpha;
  
  // Queried properties
  bool isMobile();
  bool isCollided(CatomSim* S);
  bool isTouching(CatomSim* S);
  
  // Return the string representation of CatomSim
  string toString();

  // Return the povray representation of CatomSim
  string toPovObject();

  // Allocates code modules
  void loadCodeModules(string);

  bool updateFileModule( StateFile::ByteData32* content, uint8 version );
  
  // Dummy Constructor for internal use only, this means NOT you.
  CatomSim() : C(0) { }

  // Constructor(GUID, location, qx, qy, qz, red, green, blue, alpha)
  // Note: needs CatomWorld at *worldPtr to be set up first!
  CatomSim(unsigned long, Point3D, double, double, double, 
	   uint8, uint8, uint8, uint8);

  // Duplicate Constructor(catom pointer, GUID)
  // Warning - this is intended for WorldBuilder use only
  CatomSim(CatomSim*, unsigned long);

  // Destructor
  ~CatomSim();
  
  // Fix up neighbors lists in Catom structures
  static void updateAllNeighbors();
  void preMoveUnlinkNeighbors();
  void postMoveRelinkNeighbors();

  // Apply forces
  static void applyMagnetStates();
  static void applyAllMagnetForces();
  static void applyAllMagicForces();

  // Stats
  void dumpNetworkingStats();
};




#endif /* __CATOMSIM_H */
