#ifndef __CARPHYSICS
#define __CARPHYSICS

#include "fileio.h"
#include "vectors.h"
#include "entities.h"
#include "gameinitexit.h"

#define kMaxWheels 6

enum{
	kLightFlagDriveLight=1<<0,
	kLightFlagFogLight=1<<2,
	kLightFlagRevLight=1<<3,
	kLightFlagBrakeLight=1<<4,
	kLightFlagLIndLight=1<<5,
	kLightFlagRIndLight=1<<6,
	kLightFlagHorn=1<<7
};

typedef struct{
	tVector3 pos;
	int texture;			
	float powered;		
	float maxAngle;				
	float maxSuspension;	//m
	float radius;	//m
	float width;
	float loadSensitivity;
	float stickyness;
	float grip;
	float rollCenter;
	float braked,handbraked;
	float tolerance;
	float inertia;
	float tilt;
	float friction;
	tFileRef model;
	tFileRef customBrakeModel;
	int noShadow;
} tWheelDefinition;

#define kFatalDamage 400
#define kEngineDamage 300
#define kSuspensionDamage 200


typedef struct{
	char name[64];
	char describtion[256];
	int requirements,conflicts;
	float mass;
	float frontLift,rearLift;
	float frontMaxSuspension,rearMaxSuspension;
	float frontWheelWidth,rearWheelWidth;
	float frontAirResistance;
	float powerPercent,torquePercent;
	float finalDriveRatio,topGearRatio;
	float engineInertia;
	float gearSwitchTime;
	float differentialLockCoefficient;
	float frontSwayBar,rearSwayBar;
	float track;
	float maxRPM;
	float exhaustFire;       
	float damperStrength;
	tVector3 massCenter;
	int hasGraphic;
	tFileRef model;
	int price;
	int group;
} tAddOnDefinition;

typedef struct{
	float frontAirResistance,sideAirResistance,topAirResistance;   
	float frontLift,rearLift;
	float mass;					//kg
	float power;				//W
	float torque;				//Nm
	float powerRPM,torqueRPM;	//revs per minute  
	float clutchRPM;
	float idleRPM,jerkRPM,maxRPM;  
	float shiftUpRPM,shiftDownRPM,shiftUpRPMFix;
	float finalDriveRatio;  
	float differentialLockCoefficient;
	float supsensionFriction,damperStrength;			
	float engineInertia;
	float engineFriction,engineBaseFriction,engineRPMFriction;
	float maxClutchTorqueTransfer;
	float zeroRPMSoundGain,fullRPMSoundGain,zeroThrottleSoundGain,fullThrottleSoundGain;                                                                                                                                                                                                  
	float zeroRPMSoundPitch,fullRPMSoundPitch,zeroThrottleSoundPitch,fullThrottleSoundPitch; 
	float gearSwitchTime;    
	float exhaustFire;       
	float frontSwayBar,rearSwayBar;      
	float aiSpeedIndex;                                                                                                                                                                      
	int numGears,numWheels,numLights,numAddOns;
	int numColors;
	int initialAddOns;
	int challengeRequirements;
	int demoAvailable,builtIn;
	tVector3 massCenter;
	tVector3 inertia;
	tVector3 steeringWheelPos;
	tVector3 driverPos;
	tVector3 exhaust1Pos,exhaust2Pos;
	tVector3 frontLicensePlatePos,rearLicensePlatePos;
	float steeringWheelAngle,steeringWheelTurns,steeringWheelRadius;
	tFileRef steeringWheelTexture;
	tFileRef model,interiorModel,shadowModel;
	tFileRef engineSample,hallSample,turboSample,hornSample;
	float hornPitch;
	int numCollBoxes;
	int noDriverModel;
	float maxCollRadius;
	float *gearRatios;
	tWheelDefinition *wheels;
	tLightDefinition *lights;
	tAddOnDefinition *addOns;
	tVector3 *colors;
	int *colorLoaded;
	tCollBox *coll;
	char carName[64];
	int year;
	int magic;
	int secret;
	int price;
	float displacement;
	float turboGain;
} tCarDefinition;

typedef struct{
	float angle;
	float suspension;	//m
	float slipVelo,slip,slipAngle;
	float rotation;
	float angularVelo;
	float glow;
	int lastTrack;
	int onGround;
	int surfaceType;
} tWheelPhysics;

#define kNumLastCollisions 32
typedef struct{
	int frameCount;
	tVector3 attackPoint;
	tVector3 veloDiff;
	float rotationFactor;
} tCollisionStruct;

typedef struct{
	tCarDefinition car;
	int addOns;				//flags for add-ons installed.
	int color;
	float aiPowerCycle;		//for AI cars: start of AI power cycle which makes AI cars behave more randomly
	float aiRouteCycle;		
	int gear;				//current gear car is in
	int lastGear;
	int lightFlags;			//which lights are on
	float echo;				//is the car in a tunnel?
	int lap;				//internal lap counter for position determination (not neccesarily ==lapCount)
	int lapCount;			//lap counter
	int wrongDriectionFrames;	//number of Frames the car is moving into the wrong Direction
	int lapTimes[kMaxLaps+1];	//frame Count each time the finish line was crossed
	int finishTime;				//frame Count the race was finished or is prognosed to be finished
	int lappedPlayers[kMaxPlayers];
	int averageSpeedFrames;		//number of frames used to calculate average speed so far.
	float maxSpeed,averageSpeed,accel100,accel200,accelQuarter,accelKM,odo;
	float position;
	int checkPoint;
	float lead;
	float rpm;
	float engineAngularVelo,drivetrainAngularVelo;
	float clutchTorque;
	float throttle,oldThrottle,steering,brake,arcadeBrake,handbrake,clutch;
	float idleThrottle;
	float lastGearSwitch;
	float arcadeSteerVelo,arcadeDraftBoost;
	float maxSlip,maxAngle;
	float noisePriority;
	float dirt;
	int crashTime;			//the last frame in which all four wheels have been on the ground.
	int stuckTime;			//the last frame in which the car seemed to make some progress (ai)
	int collision;			//has the car collided with something solid this frame? (for getting stuck detection)
	int onGround;			
	tGameEntity *overtaking;
	int overtakeSide;
	float overTakeProgress;
	tVector3 lastSamplePos;
	float dirtStretch[5];
	tWheelPhysics wheels[kMaxWheels];
	UInt64 regCode;
	char *plateName;
	float damage;
	float turboRPM;
	tCollisionStruct lastCollisions[kNumLastCollisions];
} tCarPhysics;

typedef struct{
	tVector3 pos,velo,groundNormal;
	tVector3 roadForce;
	int onGround;
	float bump;
	float inertia;
	float oldAngle;
	float normalForce,suspensionForce;
} tWheelCalcData;

void InstallCarAddOns(tCarPhysics *phys);
float CalcDraftFactor(tGameEntity *car1);
void CarPhysicsEntity(tGameEntity *carEntity);
void CarMotionEntity(tGameEntity *carEntity);

#endif