#include <prcore/prcore.hpp>


#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glext.h> // what's with including one locally
#include <X11/extensions/xf86vmode.h> // is this the one?

using namespace prcore;



struct ContextGLX
{
	GLXContext glXContext;
};

static Array<ModeGL> ModeList;
static XF86VidModeModeInfo **modes; 
bool WindowGL::EnumModeList()
{
  int major, minor; // XF86 Version Numbers
  int event_base, error_base;
  int i,n;
  
  // check if extension is availible!

  if(XF86VidModeQueryVersion(mWinHandle.dpy,&minor, &major) && XF86VidModeQueryExtension(mWinHandle.dpy,&event_base,&error_base))
    {
      printf("minor: %d, major: %d, event_base: %d, error_base: %d\n",minor, major, event_base, error_base);
      
      // query all modes
      XF86VidModeGetAllModeLines(mWinHandle.dpy, DefaultScreen(mWinHandle.dpy),&n, &modes);
      
      for(i=0;i<n;i++)
	{
	  ModeGL mode;
	  mode.width=modes[i]->hdisplay;
	  mode.height=modes[i]->vdisplay;
	  mode.bits=0;
	  mode.frequency=0;
	  
	  ModeList.PushBack(mode);
	}
      return true;
    }	
  return false;

}


WindowGL::WindowGL()
{
  //	if ( !ModeList.GetSize() )
  //{
  //EnumModeList();
		//}
}


WindowGL::~WindowGL()
{
	RestoreMode();
}


int WindowGL::GetModeCount() const
{
	return ModeList.GetSize();
}


ModeGL WindowGL::GetMode(int index) const
{
	assert( index>=0 && index<= ModeList.GetSize() );
	return ModeList[index];
}


bool WindowGL::SetMode(const ModeGL& mode)
{
  int i=0;

  if ( !ModeList.GetSize() )
    {
      EnumModeList();
    }
  
  while(mode.width!=ModeList[i].width && mode.height!=ModeList[i].height)
    i++;

   if(i >= 0 && i <= ModeList.GetSize() )
     {
       XMoveWindow(mWinHandle.dpy, mWinHandle.win, 0,0);
       XResizeWindow(mWinHandle.dpy, mWinHandle.win,mode.width,mode.height);
       
       //  modes[i]->htotal=mode.height;
       //modes[i]->vtotal=mode.width;
       //printf("htotal: %d\n",modes[i]->htotal);
       //printf("vtotal: %d\n",modes[i]->vtotal);

	
// XSetWindowBorderWidth(mWinHandle.dpy, mWinHandle.win,0);

       // can have a if here... not worried yet
       XF86VidModeSwitchToMode(mWinHandle.dpy, DefaultScreen(mWinHandle.dpy),modes[i]);
       
       XF86VidModeSetViewPort(mWinHandle.dpy, DefaultScreen(mWinHandle.dpy), 0, 0);
       XF86VidModeLockModeSwitch(mWinHandle.dpy, DefaultScreen(mWinHandle.dpy),1); // lock vidmode lock
      
       XGrabKeyboard (mWinHandle.dpy,mWinHandle.win, False, GrabModeAsync, 
		      GrabModeAsync, CurrentTime);
  /* Get exclusive mouse access */

       XGrabPointer (mWinHandle.dpy, mWinHandle.win, True,
		     PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
		     GrabModeAsync, GrabModeAsync, None, None, CurrentTime);

       HideCursor();

      return true;
       
       
  //      else return false;
      }
   return false;
			    
}

bool WindowGL::RestoreMode()
{
  int n;
  XF86VidModeGetAllModeLines(mWinHandle.dpy, DefaultScreen(mWinHandle.dpy),&n, &modes);

    printf("Restore Mortade Hdisplay %d\n",modes[0]->hdisplay);
    printf("Restore Mortade vdisplay %d\n",modes[0]->vdisplay);

  // why the fuck doesn't this work??
    XF86VidModeLockModeSwitch(mWinHandle.dpy, DefaultScreen(mWinHandle.dpy),1); // unlock vidmode lock
   XF86VidModeSwitchToMode(mWinHandle.dpy, DefaultScreen(mWinHandle.dpy),modes[0]); // 0 should be original mode  
   XF86VidModeSetViewPort(mWinHandle.dpy, DefaultScreen(mWinHandle.dpy), 0, 0);
  
   ShowCursor();
  return true;
  
}


ContextGL* WindowGL::CreateContext(InitGL* init)
{
  if(!mWinHandle.win)
    return NULL;
  
  if ( !ModeList.GetSize() )
    {
      EnumModeList();
    }

 
  ContextGLX *context = new ContextGLX();
  

  

  context->glXContext = glXCreateContext(mWinHandle.dpy, mWinHandle.VisualInfo, NULL, True);
  if(context->glXContext == NULL)
  {
    printf("Could not create rendering context.\n\r");
    return NULL;
  }

  // set context
  SetContext( (ContextGL*)context );
  
  return (ContextGL*)context;
  

}


void WindowGL::DeleteContext(ContextGL* context)
{
	ContextGLX* ctx = (ContextGLX*)context;
       	glXDestroyContext(mWinHandle.dpy,ctx->glXContext );
	delete ctx;

	mCurrentContext = NULL;
}


void WindowGL::SetContext(ContextGL* context)
{
	ContextGLX* ctx = (ContextGLX*)context;
	if ( ctx )
	  glXMakeCurrent(mWinHandle.dpy, mWinHandle.win,ctx->glXContext);

	mCurrentContext = context;
}


void WindowGL::PageFlip(bool retrace)
{
	ContextGLX* ctx = (ContextGLX*)mCurrentContext;
	if ( ctx )
	{
	  glXSwapBuffers(mWinHandle.dpy, mWinHandle.win); 
	}

}
