/*
** vertex.c for Factory 0.1
**
** Made by caput_r and yousfi_r
** Login caput_r <caput_r@epita.fr> yousfi_r <yousfi_r@epita.fr>
**
** Started on  Tue Sep 27 01:34:52 2005 remi caput
** Last update Sun Nov 19 03:15:16 2006 
*/

#include "vertex.h"

struct s_vertex	gl_vertex;

float	VTX_GetFps (void)
{
	if (gl_vertex.speed == 0)
		return 0.0f;

	return 1000.0f * gl_vertex.factor / gl_vertex.speed;
}

int						VTX_Init (int width, int height, int bpp, char fullscreen)
{
	const SDL_VideoInfo	*infos;

	memset (&gl_vertex, 0, sizeof (gl_vertex));

	if (SDL_Init (SDL_INIT_VIDEO) < 0)
		return 1;

	if ((infos = SDL_GetVideoInfo ()) &&
	    (gl_vertex.screen.surface = SDL_SetVideoMode (width, height, bpp, SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | (infos->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE) | (fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE))))
	{
		VTX_InternalReset ();
		VTX_ScrResize (width, height);

		gl_vertex.factor = 1;
		gl_vertex.ready = 1;
		gl_vertex.time = 0;

		return 0;
	}

	SDL_Quit ();

	return 1;
}

void	VTX_InternalReset (void)
{
	glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
	glClearDepth (1.0f);
	glDepthFunc (GL_LESS);
	glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
	glShadeModel (GL_SMOOTH);
}

int					VTX_Loop (GLuint wait)
{
	SDL_Event		event;
	unsigned int	time;

	time = SDL_GetTicks ();

	if (gl_vertex.time)
	{
		while (time - gl_vertex.time < wait)
			time = SDL_GetTicks ();

		gl_vertex.speed = gl_vertex.factor * (time - gl_vertex.time);
	}
	else
		gl_vertex.speed = 0;

	gl_vertex.input.mouse_x = 0;
	gl_vertex.input.mouse_y = 0;
	gl_vertex.time = time;

	while (SDL_PollEvent (&event))
	{
		if (event.type == SDL_KEYDOWN)
		{
			gl_vertex.input.button[event.key.keysym.sym] = 1;
			gl_vertex.input.last = event.key.keysym.sym;
			gl_vertex.input.pending = 1;
		}
		else if (event.type == SDL_KEYUP)
			gl_vertex.input.button[event.key.keysym.sym] = 0;
		else if (event.type == SDL_MOUSEMOTION)
		{
			gl_vertex.input.mouse_x = event.motion.xrel;
			gl_vertex.input.mouse_y = event.motion.yrel;
		}
		else if (event.type == SDL_MOUSEBUTTONDOWN)
		{
			gl_vertex.input.button[event.button.button] = 1;
			gl_vertex.input.last = event.key.keysym.sym;
			gl_vertex.input.pending = 1;
		}
		else if (event.type == SDL_MOUSEBUTTONUP)
			gl_vertex.input.button[event.button.button] = 0;
		else if (event.type == SDL_VIDEORESIZE)
			VTX_ScrResize(event.resize.w, event.resize.h);
		else if (event.type == SDL_QUIT)
			gl_vertex.exit = 1;
	}

	SDL_GL_SwapBuffers ();
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	return gl_vertex.exit;
}

void	VTX_ScrDimention (enum vtx_dimention dimention)
{
	if ((gl_vertex.screen.dimention = dimention) == VTX_DIMENTION_3D)
	{
		glEnable (GL_DEPTH_TEST);
		glMatrixMode (GL_PROJECTION);
		glLoadIdentity ();
		gluPerspective (45.0f, (float)gl_vertex.screen.width / (float)(gl_vertex.screen.height ? gl_vertex.screen.height : 1), 0.1, 1000);
		glMatrixMode (GL_MODELVIEW);
		glLoadIdentity ();
	}
	else
	{
		glDisable (GL_DEPTH_TEST);
		glMatrixMode (GL_PROJECTION);
		glLoadIdentity ();
		glOrtho (0, gl_vertex.screen.width, 0, gl_vertex.screen.height, -1, 1);
		glMatrixMode (GL_MODELVIEW);
		glLoadIdentity ();
	}
}

void	VTX_ScrResize (GLuint width, GLuint height)
{
	gl_vertex.screen.height = height;
	gl_vertex.screen.width = width;

	glViewport (0, 0, width, height);

	VTX_ScrDimention (gl_vertex.screen.dimention);
}

void	VTX_SetMouse (char visible, char grabbed)
{
	SDL_ShowCursor (visible ? SDL_ENABLE : SDL_DISABLE );
	SDL_WM_GrabInput (grabbed ? SDL_GRAB_ON : SDL_GRAB_OFF);
}

void	VTX_SetWindow (const char* title, const char* icon)
{
	SDL_WM_SetCaption (title, icon);
}

void	VTX_Stop (void)
{
	if (gl_vertex.ready)
	{
		SDL_FreeSurface (gl_vertex.screen.surface);
		SDL_Quit ();

 		gl_vertex.ready = 0;
	 }
}

# ifdef __WIN32__

#include <strings.h>
#include <windows.h>

#ifdef __cplusplus
extern "C" {
#endif

//int	SDL_main (int argc, char** argv);

#ifdef __cplusplus
}
#endif

int APIENTRY	WinMain (HINSTANCE hInstance __attribute__((unused)), HINSTANCE hPrevInstance __attribute__((unused)), LPSTR lpCmdLine, int nCmdShow __attribute__((unused)))
{
	char**		arga;
	char**		argv;
	int			argc;
	int			err;
	int			i;

	while (*lpCmdLine != '\0' && *lpCmdLine <= ' ')
		++lpCmdLine;

	argc = 1;
	argv = NULL;

	for (err = -1; err == -1; )
	{
		if (!(arga = (char**)realloc (argv, (argc + 1) * sizeof (*argv))))
			err = 1;
		else
		{
			argv = arga;

			if (*lpCmdLine == '\0')
			{
				argv[0] = "<exe_name>";
				argv[argc] = NULL;

				err = SDL_main (argc, argv);
			}
			else
			{
				for (i = 1; lpCmdLine[i] != '\0' && lpCmdLine[i] > ' '; )
					++i;

				if (!(argv[argc] = malloc ((i + 1) * sizeof (*argv))))
					err = 1;
				else
				{
					memcpy (argv[argc], lpCmdLine, i * sizeof (*argv));
					argv[argc++][i] = '\0';
				}

				if (lpCmdLine[i] == '\0')
					lpCmdLine += i;
				else
					lpCmdLine += i + 1;
			}
		}
	}

	while (argc)
		free (argv[--argc]);

	if (argv)
		free (argv);

	return err;
}

#endif
