#include "globals.h"


void Render_Window :: render(){
          double factor=10;
          double ux=-cos((camera->azimut+45)*3.1416/180.);
          double uz=-sin((camera->azimut+45)*3.1416/180.);
    double d=0.2;
    puts("  checking mouse state");
    if(has_focus)
    {
        if(Fl::get_key(FL_Up))      camera->targetz+=ux/factor,camera->targetx+=uz/factor;
        if(Fl::get_key(FL_Down))    camera->targetz-=ux/factor,camera->targetx-=uz/factor;
        if(Fl::get_key(FL_Right))     camera->targetz+=uz/factor,camera->targetx-=ux/factor;
        if(Fl::get_key(FL_Left))    camera->targetz-=uz/factor,camera->targetx+=ux/factor;
//        if(Fl::event_button ()==FL_LEFT_MOUSE)
        if(Fl::event_state()&FL_BUTTON1)
        {


          camera->targetx+=camera->mouse_dx*ux/factor+camera->mouse_dy*uz/factor;
          camera->targetz+=-camera->mouse_dx*uz/factor+camera->mouse_dy*ux/factor;
        }
        if(Fl::event_state()&FL_BUTTON2||Fl::event_state()&FL_BUTTON3)
        {
          camera->size+=camera->mouse_dy/4.;
          if(camera->size<1)camera->size=1;
          if(camera->size>200)camera->size=200;
        }
    }
    glClearColor(0,0,0,0);
    glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_ALPHA_TEST);
    glDisable(GL_ALPHA_TEST);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(camera->fov,1,max(0.1,camera->distance-100),max(10.,camera->distance-100)+200);

        static GLint fogMode;
        glEnable(GL_FOG);
        GLfloat fogColor[4] = {0., 0., 0.0, 1.0};
        fogMode = GL_EXP;
        glFogi (GL_FOG_MODE, fogMode);
        glFogfv (GL_FOG_COLOR, fogColor);
        glHint (GL_FOG_HINT, GL_DONT_CARE);
        glFogf (GL_FOG_START, 0.5);
        glFogf (GL_FOG_END, 100);
        glFogf (GL_FOG_DENSITY, 0.0);


/*    glTranslated(0,0,-camera->distance);
    glRotated(camera->zenit,1,0,0);
    glRotated(-camera->azimut-45,0,1,0);*/



    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
        float light_position2[]= {0,0.5,1,0};
        glLightfv(GL_LIGHT0,GL_POSITION,light_position2);

    glTranslated(0,0,-camera->distance);
    glRotated(camera->zenit,1,0,0);
    glRotated(-camera->azimut-45,0,1,0);

/*    glRotated(camera->azimut+45,0,1,0);
    glRotated(-camera->zenit,1,0,0);
    glTranslated(0,0,camera->distance);*/



    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glAlphaFunc(GL_GREATER,0.5);
    glEnable(GL_ALPHA_TEST);
    //glDisable(GL_ALPHA_TEST);
    glColor3f(1,1,1);
    glPushMatrix();
    glTranslated(-camera->targetx,0,-camera->targetz);
    glDisable(GL_LIGHTING);
    glDisable(GL_LIGHT0);
    glDisable(GL_TEXTURE_2D);
    glColor4d(0.2,0.2,0.3,1);
    puts("  drawing grid");
    glBegin(GL_LINES);
    for(int i=0;i<=64;i++)
    {
        glVertex3d(i,0,0);
        glVertex3d(i,0,64);
    }
    for(int i=0;i<=64;i++)
    {
        glVertex3d(0,0,i);
        glVertex3d(64,0,i);
    }
    glEnd();

    glColor4d(1,1,1,1);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_COLOR_MATERIAL);
    glDisable(GL_LIGHTING);
    glDisable(GL_BLEND);
    glEnable(GL_TEXTURE_2D);
    puts("  binding map texture");
    glBindTexture(GL_TEXTURE_2D, lba_map_gl->texture_name);
    puts("  texture loaded");
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
//    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);

    if(has_light)
    {
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        float light_ambient[] = {0.3,0.3,0.3,1};
        float light_diffuse[] = {0.7,0.7,0.7};
        float light_specular[] = {1.,1.,1.,1};



        float mat_shininess=0.;
        float light_position[]= {0.5,0.8,0.3,0};
        glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
        glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
        glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
//        glLightfv(GL_LIGHT0,GL_POSITION,light_position);
		float mat_ambiant2[]={0.5,0.5,0.5,1};
		float mat_diffusion2[]={0.7,0.7,0.7,1};
		float mat_specular2[]={1,1,1,1};
        float mat_emission2[] = {0.0,0.0,0.0,1};


//		glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emission2);
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambiant2);
	//	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffusion2);
//		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular2);
//		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10);
	//	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0);

    }
    else
    {
        glDisable(GL_LIGHTING);
        glDisable(GL_LIGHT0);
    }
    if(has_texture)
        glEnable(GL_TEXTURE_2D);
    else
        glDisable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);
    //glDisable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    //glDisable(GL_CULL_FACE);
    //glDisable(GL_ALPHA_TEST);

    puts("  calling display list");



    glCallList(lba_map_gl->list_name);
    glPopMatrix();
    glDisable(GL_ALPHA_TEST);
    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}




void IdleCallback(void* pData)
{
    Render_Window* pWindow = reinterpret_cast<Render_Window*>(pData);
    pWindow->redraw();
}


Render_Window::Render_Window(Camera *c,int x,int y,int w,int h,const char *l=0)
    : Fl_Gl_Window(x,y,w,h,l)
{
    camera=c;
    has_focus=false;
    initglflag=true;
    has_texture=true;
    has_light=true;
    LBA2_flag=false;
    change_map_flag=false;
//typedef void (APIENTRY * PFNGLGENBUFFERSPROC) (GLsizei i,GLuint *name);
//PFNGLGENBUFFERSPROC  glGenBuffers = NULL;
//extern PFNGLGENBUFFERSPROC glGenBuffers;
//extern PFNGLBINDBUFFERARBPROC glBindBuffer;
//extern PFNGLBUFFERDATAPROC glBufferData;
//typedef void (APIENTRY * PFNGLGENBUFFERSPROC) (GLfloat red, GLfloat green, GLfloat blue);
   mode(FL_RGB | FL_ALPHA | FL_DEPTH | FL_DOUBLE);
   Fl::add_idle(IdleCallback, this);
}


Render_Window::~Render_Window()
{}





void Render_Window::draw()
{
   puts("drawing a frame");
   if (initglflag)
   {
      initgl();
      initglflag = false;
   }
   if(change_map_flag)
   {
    change_map();
    change_map_flag=false;
   }
   render();
   puts("end of rendering");
}

void Render_Window::initgl(void)
{
    glClear(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor (0.0, 0.0, 0.0, 0.0);
    int taille;
    glGetIntegerv( GL_MAX_TEXTURE_SIZE, &taille );
    printf("%d",taille);
    int i,j,k;
    lba_map_gl=new LBA_MAP_GL(0,0);
    //strcpy(map_name,"Citadel Island, Prison");
    glEnable(GL_TEXTURE_2D);
    glColor3f(1,1,1);
    glColorMask(1,1,1,1);
    GLint alpha_bits;
    glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
    printf("The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glShadeModel(GL_SMOOTH);
}

void Render_Window::change_map(void)
{
    delete lba_map_gl;
    lba_map_gl=new LBA_MAP_GL(NUM_MAP,LBA2_flag);

}

int Render_Window::handle(int event)
{
         int key;
//   if(fl_isfocus()){
   switch (event)
   {
      case FL_ENTER:puts("enter");has_focus=true;Fl::focus(this);return 1;
      case FL_LEAVE:puts("leave");has_focus=false;return 1;
      case FL_FOCUS:;puts("focus");has_focus=true;return 1;
      case FL_UNFOCUS:puts("unfocus");has_focus=false;return 1;
      case FL_PUSH:puts("push ");return 1;
      case FL_RELEASE:puts("release ");return 1;
      case FL_MOVE:/*printf("move ");*/return 1;
      case FL_MOUSEWHEEL:printf("wheel ");return 1;


      case FL_KEYDOWN://overriding default arrow keys action. Default result in switching widget = losing keyboard focus
         key = Fl::event_key();
         switch (key)
         {
            case FL_Left:
            case FL_Right:
            case FL_Up:
            case FL_Down:
            return 1;
         }
      case FL_KEYUP:
         key = Fl::event_key();
         switch (key)
         {
            case FL_Left:
            case FL_Right:
            case FL_Up:
            case FL_Down:
            return 1;
         }
        return 1;
        redraw();
   }

   return Fl_Gl_Window::handle(event);
}

