#ifndef H_RENDERER
#define H_RENDERER

#include "content.h"
#include "actor.h"
#include "particleSystem.h"
#include "textfile.h"

#define BUFSIZE 512



using namespace std;

class Input;

class Renderer{

public:

       static map <string, actorID> actorInfo;    //for RTTY - all types of actors this program has
                                                  //and type/size information for them
       static GLuint selectBuf[BUFSIZE];          //for picking

       //lists
       static vector <Actor*> actorList;          //all created actors go here

       static map <string, GLuint> textureList;        //all loaded textures go here
       static map <string, GLuint> shaderList;    //all loaded shaders go here

       static GLuint frameBufferTexture;

       static string backgroundTex;
       static Vector4f backgroundColor;

       static bool bRenderShadow;


       //Physics using ODE
       static bool bUpdatePhysics;                //call physicsUpdate or not

       //General and Screen stuff
       static bool bFullscreen;
       static int screenX,screenY;                //screen width, height
       static int nearClip, farClip;              //clipping planes

       static int frames;                         //amount of frames rendered
       static double currentTime,                 //time since program start,
                     deltaTime,                   //time since last frame
                     physicsTime;                 //time for physics step (sometimes deltaTime is too small to advance physics...)

       //Control stuff
       static float lookSpeed;                    //general turn speed
       static float moveSpeed;                    //general move speed

       static float fov;                          //field of view
       static Vector3f *camLoc;                   //camera Location
       static Vector3f *camLook;                  //camera Rotation

       static Vector3f lightLoc;                  //light Location
       static Vector3f ambient;                  //ambient Light

       static Content *content;                   //the list of things we create at program start


        //Frame Buffer Objects for shadow rendering

        GLuint shadow_tx; // the shadow texture
        GLuint shadow_fb; // the framebuffer object to render to that texture
        GLuint depthBuffer; // a renderbuffer for depth
        GLuint shadow_sz; // the shadow map size

        Matrix4f cameraProjectionMatrix;
        Matrix4f cameraViewMatrix;
        Matrix4f camViewProjMatrix;

        Matrix4f lightViewMatrix;
        Matrix4f lightProjectionMatrix;
        Matrix4f lightViewProjMatrix;



       Renderer();
       virtual ~Renderer();

       //***************************************
       //this is stuff we can update easily
       //***************************************
       virtual void fillGlobalLists();                  //for RTTY - generate actorInfo
       virtual void initWindow(int x, int y, char* windowName);  //
       virtual void reDrawScreen(int w, int h);

       virtual void setup();                      //first thing called when program starts

       virtual void checkFBOStatus();

       virtual void update();
       virtual void physicsUpdate();

       virtual void draw();

       virtual void drawShadows();
       virtual void applyShadows();

       virtual void draw3D();
       virtual void draw2D();

       virtual void drawBackground();

       static void pick(int x, int y);                    //get the 3D coordinates from the mouse and also get the actor we're pointing at
          static void startPicking(int cursorX, int cursorY);
          static void stopPicking(int cursorX, int cursorY);
          static void processHits (GLint hits, GLuint buffer[], int cursorX, int cursorY);
          static double connectHits (GLint hits, GLuint buffer[]);

       static GLuint createNewRenderTarget();
       static GLuint LoadTextureRAW( const char * filename, int size, int wrap );
       static GLuint LoadTextureTGA( const char * filename, int size, int wrap );

    //helper functions for dealing with the renderList
       static bool removeActor(Actor * a);

      };


//*****************************************
//Template for creating Actor IDs
//*****************************************
template<typename myType>
void createActorID(myType *ref )
{
actorID *act;
act=new actorID;
//Actor
act->actorReference=ref;
act->actorType=&(typeid(*ref));
act->actorSize=sizeof(*ref);
Renderer::actorInfo[typeid(*ref).name()]=*act;
std::cout << "created a reference for " << typeid(*ref).name() << "\n";
std::cout << "created a reference for " << act->actorType->name() << "\n";
}

//*****************************************
//Template for creating an Actor
//*****************************************
template <typename myType>
void addActor (myType *a)
{
a = new myType;

Renderer::actorList.push_back(a);
Renderer::actorList.back()->setup();
}


#endif
