#ifndef H_ACTOR
#define H_ACTOR

#include "includes.h"

#define DRAW_PLANE 0
#define DRAW_MESH 1
#define DRAW_TEA 2
#define DRAW_CUBE 3
#define DRAW_PARTICLES 4
#define DRAW_SPRITE 5



class Control;
class Input;
class InterpolationHelper;

typedef int ListID;                             //convenient way of making clear what those mean...

using namespace std;

class Actor
{
public:

       std::map <std::string, memberID> property;

       Vector3f location,
                rotation,
                scale;

       Vector3f initialLocation,
                initialRotation;

       Vector4f color;

       std::string name;

       //Shader related
       GLuint shaderProgram;
       GLuint vertexShader;
       GLuint fragmentShader;

       std::string meshFileName;                        //holds the mesh file name
       std::string shaderProgramName;
       std::string vertexShaderFileName;                   //holds the file name
       std::string fragmentShaderFileName;                 //holds the file name
       char * vertexShaderFile;               //actually holds the whole file
       char * fragmentShaderFile;             //actually holds the whole file

       std::string mesh;

       std::string texture;
       float texFactorX,                     //for now, the tiling of the texture...
             texFactorY;                     //for now, the tiling of the texture...

       int drawType;

       double elapsedTime;
       double birth;

       bool bHidden;
       bool bPickable;

       std::string soundFileName;

       bool bTextured,                      //Render options
            bAlphaBlend,
            bWireFrame,
            bDepthTest,
            bUseShader,
            bShadow,
            bFullBright;

       Control *controller;
       InterpolationHelper *mover;

       ListID nextKeyFrame;
       ListID attachedTo;

       //for radial menu
       std::vector <std::string> menuType;
       std::vector <std::string> menuProp;
       std::vector <std::string> menuName;
       std::vector <std::string> menuIcon;
       //end radial menu

       Actor();
       virtual ~Actor();

       //setup functions
       virtual void registerProperties();

       virtual void setup();
       virtual void setupShaders();
       virtual void linkShaderVariables();

       virtual void printShaderInfoLog(GLuint obj);
       virtual void printProgramInfoLog(GLuint obj);

       virtual void trigger(Actor * other);

       //runtime looping functions
       virtual void update(double deltaTime);
       virtual void updateShaders();
       virtual void draw();

       virtual void drawMesh();
       virtual void drawSprite();
       virtual void drawPlane();
       virtual void drawParticles();
       virtual void drawTeapot();
       virtual void drawCube();

       virtual void drawCollision();

       //transformation functions
       virtual void setLocation(Vector3f loc);
       virtual void setRotation(Vector3f rot);

       //save load and create
       virtual void create();
       virtual TiXmlElement* save(TiXmlElement *root);
       virtual void load(TiXmlElement *myInfo);

       //property assigning
       virtual string memberToString(memberID *mID);
       virtual void memberFromString(memberID *mID,string value);
       virtual bool setStringPropertyTo(memberID *mID,string s);

       virtual void checkReferences(int i);

       // XML parsing functions:

       virtual Vector3f readVector3f(char* cValue);
       virtual Vector4f readVector4f(char* cValue);
       virtual bool readBool(char* cValue);
       virtual GLuint readGLuint(char* cValue);
       virtual int readInt(char* cValue);
       virtual float readFloat(char* cValue);
       virtual double readDouble(char* cValue);
       virtual string readString(char* cValue);

       bool createNewActor(string actorIDName);
       bool isA(string className);
};

//*****************************************
//Template for assigning memberIDs
//*****************************************

template <typename myType>
bool setPropertyTo (memberID* mID, myType value)
{
const std::type_info* mType;
mType=&(typeid(value));

if (mID->memberType->name()==mType->name())
  {
  memcpy(mID->memberReference,&value,sizeof(value));
  return true;
  }
else
  return false;
}



//*****************************************
//Template for creating Member IDs
//*****************************************

template<typename MyType, typename ActorClass>
void createMemberID(const char* memberName, MyType *memberRef, ActorClass* base)
{
memberID mID;
//Actor
mID.memberReference=memberRef;
mID.memberType=&(typeid(*memberRef));
mID.memberSize=sizeof(*memberRef);
mID.memberName=(char*)memberName;
base->property[memberName]=mID;
}
#endif
