//
// main.cc for graviball in
//
// Made by
// Login   <@epita.fr>
//
// Started on  Sun Nov 19 14:51:54 2006
// Last update Sun Nov 19 19:22:44 2006
//

#include <stdio.h>
#include "factory/camera.h"
#include "factory/chord.h"
#include "factory/coord.h"
#include "factory/particle.h"
#include "factory/surface.h"
#include "factory/vertex.h"
#include "game/ball_list.hh"
#include "game/bonus_list.hh"
#include "game/pad.hh"
#include "map/map.hh"
#include "map/reader.hh"
#include "util/music.hh"

int							main (int argc __attribute__ ((unused)), char* argv[] __attribute__ ((unused)))
{
	GLUquadricObj*			quadric;
	struct s_bonus_list		bonus_list;
	struct s_ball_list		ball_list;
	struct s_camera			camera;
	struct s_music			music;
	struct s_pad			pad;
	struct s_particle		particle;
	struct s_surface		surface;
	float					center_x;
	float					center_y;
	float					length_x;
	bool					first;
	int						view;
	Map						map;

	if (argc < 2)
	{
		std::cout << "usage: " << argv[0] << " <map file>" << std::endl;

		return 0;
	}

	if (!CHD_Init (100, FMOD_INIT_NORMAL) && !VTX_Init (640, 480, 16, 0) && !surface_init (&surface) && !particle_init (&particle, &surface))
	{
		try
		{
			Reader	reader (argv[1]);

			reader.read (map.getMap ());
//			reader.print (map.getMap ());
		}
		catch (std::string e)
		{
			std::cerr << e << std::endl;
			return 1;
		}

		map.init ();
		quadric = gluNewQuadric ();
		gluQuadricNormals (quadric, GLU_SMOOTH);
		gluQuadricTexture (quadric, GL_TRUE);

		center_x = (map.getMap ().world.limits[0] +	map.getMap ().world.limits[1]) / 2;
		center_y = (map.getMap ().world.limits[2] +	map.getMap ().world.limits[3]) / 2;
		length_x = map.getMap ().world.limits[1] - map.getMap ().world.limits[0];
		first = true;
		view = -1;

		camera_define (&camera);
		music_init (&music);

		ball_list_define (&ball_list, &particle, &surface, quadric, map.getMap ().world.limits[0], map.getMap ().world.limits[1], map.getMap ().world.limits[2], map.getMap ().world.limits[3]);
		bonus_list_define (&bonus_list, &particle, &surface, map.getMap ().world.limits[0], map.getMap ().world.limits[1], map.getMap ().world.limits[2], map.getMap ().world.limits[3]);
		pad_define (&pad, &particle, &surface, quadric, map.getMap ().world.limits[0], map.getMap ().world.limits[1], map.getMap ().world.limits[2]);

		VTX_SetMouse (0, 1);
		VTX_SetWindow ("Graviball", NULL);
		VTX_Loop (0);

		srand (gl_vertex.time);

		music_play_random (&music, "data/musics/random");

		while (!VTX_Loop (0) && !VTX_KEY_PRESSED (SDLK_ESCAPE))
		{
			CHD_Loop ();

			bonus_list_loop (&bonus_list);
			ball_list_loop (&ball_list);
			pad_loop (&pad, &ball_list);
			particle_cycle (&particle);

			ball_list_collide (&ball_list, &pad, map.getMap ().blockGroups, &bonus_list);
			bonus_list_collide (&bonus_list, &pad, &ball_list);

			ball_list_move (&ball_list);
			bonus_list_move (&bonus_list);
			pad_move (&pad);

			if (first || VTX_KEY_HIT (SDLK_SPACE))
			{
				switch ((view = (view + 1) % 4))
				{
					case 0:
						camera_mode (&camera, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, 0);
						coord_set_pos (camera.focus, center_x, 0, 0.0f);
						coord_set_pos (camera.shift, 0.0f, 0.0f, -30.0f);
						coord_set_rot (camera.shift, 0.0f, 0.0f, 0.0f);
					break;

					case 1:
						camera_mode (&camera, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, 0);
						coord_set_pos (camera.shift, 0.0f, 0.0f, -30.0f);
						coord_set_rot (camera.shift, 0.0f, 0.0f, 0.0f);
					break;

					case 2:
						camera_mode (&camera, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, CAMERA_MODE_RELATIVE, 0);
						coord_set_pos (camera.shift, 0.0f, 0.0f, -30.0f);
					break;

					case 3:
						camera_mode (&camera, CAMERA_MODE_INSTANT, CAMERA_MODE_INSTANT, CAMERA_MODE_INSTANT, CAMERA_MODE_INSTANT, 0);
						coord_set_pos (camera.shift, 0.0f, 0.0f, 1.0f);
						coord_set_rot (camera.shift, -90.0f, 0.0f, 0.0f);
					break;
				}

				first = false;
			}

			switch (view)
			{
				case 0:
					if (VTX_KEY_PRESSED (SDL_BUTTON_RIGHT))
						camera.shift->rx -= gl_vertex.input.mouse_y;
				break;

				case 1:
					if (VTX_KEY_PRESSED (SDL_BUTTON_RIGHT))
						camera.shift->rx -= gl_vertex.input.mouse_y;

					coord_set_pos (camera.focus, pad.coord.px, 0, 0.0f);
				break;

				case 2:
					coord_set_pos (camera.focus, pad.coord.px, 0, 0.0f);
					coord_set_rot (camera.shift, -60.0f, pad.coord.px * -30.0f / length_x, pad.coord.px * -45.0f / length_x);
				break;

				case 3:
					coord_set_pos (camera.focus, pad.coord.px, pad.coord.py, 0.0f);
				break;
			}

			camera_begin (&camera);
				map.render ();
				ball_list_draw (&ball_list);
				bonus_list_draw (&bonus_list);
				pad_draw (&pad);
				particle_draw (&particle);
			camera_stop ();
		}

		music_free (&music);

		gluDeleteQuadric (quadric);
		particle_stop (&particle);
		surface_stop (&surface);

		CHD_Stop ();
		VTX_Stop ();
	}

	return 0;
}
