/***************************************************************************
 *            vamosworld.h
 *
 *  Sat Mar 26 14:05:40 2005
 *  Copyright  2005  Joe Venzon
 *  joe@venzon.net
 ****************************************************************************/

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
#ifndef _VAMOSWORLD_H

#ifdef __APPLE__ 
#include "definitions_mac.h" 
#else 
#include "definitions.h" 
#endif 

 
#include <stdio.h>			// Header File For Standard Input/Output
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>
#ifdef __APPLE__
#include <SDL_image/SDL_image.h>
#else
#include <SDL/SDL_image.h>
#endif
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <cassert>

using namespace std;

#include "font.h"
#include "quat.h"
#include "keyman.h"
#include "camera.h"
#include "particles.h"
#include "messageq.h"
#include "sound.h"
#include "timer.h"
#include "controls.h"
#include "replay.h"
#include "mouse.h"
#include "gamestate.h"
#include "multiplay.h"
#include "track.h"
#include "ai.h"
#include "trackmap.h"
#ifdef ENABLE_FORCE_FEEDBACK
#include "forcefeedback.h"
#endif

#include "globals.h"

#include <vamos/world/World.h>
#include <vamos/body/Gl_Car.h>
#include <vamos/body/Car.h>
#include <vamos/body/Wheel.h>
#include <vamos/body/Fuel_Tank.h>

#define MAX_TRIM_LOOPS 5000

#define AUTO_CLUTCH_THRESH 200.0f
#define AUTO_CLUTCH_MARGIN 100.0f
#define AUTO_CLUTCH_ENGAGE_TIME 1.0f

enum CameraMode { CMChaseRigid=0, CMChase=1, CMOrbit=2, CMHood=3, CMFree=4, CMInCar=5, CMExternal=6, CMExtFollow=7 };

enum CONTROLLERTYPE { CONT_NONE=0, CONT_PLAYERLOCAL=1, CONT_PLAYERREMOTE=2, CONT_AI=-1, CONT_REPLAY=3 };

#define LIGHT_MAP_RESOLUTION 4

class VAMOSWORLD
{
private:
	Vamos_World::World * world;
	float steerpos;
	CameraMode cammode;
	bool joyinfo;
	bool propsteer;
	int oldseg;
	bool initdone;
	float shift_time;
	ofstream error_log;
	TEXTURE_HANDLE tachbase, tachredband, tachband, speedo, needle, fuelgauge, fgbox;
	TEXTURE_HANDLE m_ballh, m_sliderh, m_ballv, m_sliderv;
	TEXTURE_HANDLE sphere_reflection;
	TEXTURE_HANDLE cube_reflection;
	TEXTURE_HANDLE cube_lighting;
	TEXTURE_HANDLE cube_lighting_car;
	TEXTURE_HANDLE car_shadow;
	TEXTURE_HANDLE abs_indicator;
	TEXTURE_HANDLE tcs_indicator;
	double l_timefactor, l_fps;
	SDL_Joystick * joyinfo_js;
	SDL_Joystick ** joyinfo_jsarray;
	TRACK * track_p;
	float steervals[2];
	VERTEX cam_lastpos;
	VERTEX cam_lastpos2;
	VERTEX cam_lastvel;
	VERTEX cam_lastaccel;
	VERTEX cam_jerk;
	int tire_source[4];
	VERTEX oldtirepos[4];
	float lastcamchange; //used by the external camera mode
	VERTEX oldcampos;
	bool camneedupdate;
	bool MPH;
	bool auto_clutch;
	bool auto_trans;
	bool display_hud;
	bool input_graph_enabled;
	bool trackmap_enabled;
	bool car_shadows_enabled;
	float button_ramp;
	map<string, float> dgtl_ctrl_anlg_val;
	map<string, bool> control_held;
	Uint32 auto_shift_time;
	bool tcs, abs;
	AI* ai;
	int lighting;
	int reflections;
	float mousezoom;
	bool joy_200_degree;
	float speed_sens;
	TRACKMAP* trackmap;
#ifdef ENABLE_FORCE_FEEDBACK
	FORCEFEEDBACK * force_feedback;
	string ff_device;
	float ff_gain;
	bool ff_invert;
#endif

	void PhysUpdate(float dt);
	void draw_cars(bool draw_interior, bool draw_focused_car);
	void DrawHUD();
	void draw_shadows();
	void DisplayJoyInfo();
	void build_track_shot();
	void ProcessControls(SDL_Joystick ** js, float timefactor, float fps);
	void steer_to(float val, float timefactor, float fps);
	void steer_set(float val, bool left);
	void steer_commit();
	void DoOp(Vamos_World::Car_Information * c, string dofunction, float dovalue, float dotime, bool held, float timefactor, float fps);
	void ShadowTexCoord(VERTEX &carpos, QUATERNION &carorientation, VERTEX & shadowdim, VERTEX &vert, float roadheight);
	float DownshiftPoint( Vamos_World::Car_Information * c, int gear );
	
	bool lighting_enable;
	
	GLuint dynamic_cube_reflection_texture;
	GLuint dynamic_cube_lighting_texture;
	
	unsigned char light_pixels[LIGHT_MAP_RESOLUTION*LIGHT_MAP_RESOLUTION*3*6];

public:
	VAMOSWORLD();
	~VAMOSWORLD();
	void Init (TRACK* track);
	void Update(float timefactor, float fps, SDL_Joystick ** js);
	void UpdateSettings();
	void reset();
	void LoadHUD();
	void UnloadHUD();
	void DeInit();

	void Draw();
	void DrawShadows();
	void DrawCars();
	void DrawTopLevel();

	void SetCameraMode(CameraMode newmode);

	Vamos_Body::Car * GetPlayerCar() { return GetCar(CONT_PLAYERLOCAL)->car; }
	Vamos_World::Car_Information * GetCar(CONTROLLERTYPE p);
	void add_car (Vamos_Body::Gl_Car* car);
	void clear_cars();
	void FuelPlayerCar();
	void ActivateTextureBasedLighting(bool goofy) {ActivateTextureBasedLighting(goofy, false);}
	void ActivateTextureBasedLighting(bool goofy, bool car);
	void DeactivateTextureBasedLighting();
	bool StaticCubeLighting();
	bool DynamicCubeLighting();
	bool StaticCubeReflectionMapping();
	bool DynamicCubeReflectionMapping();
	//void SetLighting(bool enable) {lighting_enable=enable;}
	GLuint GetReflectionTexture(int id) {return dynamic_cube_reflection_texture;}
	GLuint GetLightingTexture(int id) {return dynamic_cube_lighting_texture;}
	void DisplayRaceResults();
	
	unsigned char * GetLightPixels (int cubefaceid) {return light_pixels+cubefaceid*LIGHT_MAP_RESOLUTION*LIGHT_MAP_RESOLUTION*3;}
	int GetLightPixelsSize() {return LIGHT_MAP_RESOLUTION;}
	
	bool Loaded() {return initdone;}
};

#define _VAMOSWORLD_H
#endif /* _VAMOSWORLD_H */
