#include <Irrlicht.h>
#include <IPhysics.h>

#pragma comment(lib, "Irrlicht.lib")
#pragma comment(lib, "IPhysics.lib")

bool doRun;
IrrlichtDevice* device;

class CEventReceiver : public IEventReceiver
{
public:
	CEventReceiver(IPhysicsCar* car)
	{
		m_car = car;

		for(s32 i=0; i<KEY_KEY_CODES_COUNT; i++)
		{
			m_keys[i] = false;
		}
	}
	~CEventReceiver()
	{
	}
	bool OnEvent(SEvent event)
	{
	if(event.EventType == EET_KEY_INPUT_EVENT)
	{
		if(event.KeyInput.Key == KEY_KEY_W)
		{
			if(!m_keys[KEY_KEY_W])
			{
				m_keys[KEY_KEY_W] = true;
				m_car->setThrottlePercent(100.0f);
			}
			else if(event.KeyInput.PressedDown == false)
			{
				m_keys[KEY_KEY_W] = false;
			}
		}
		if(event.KeyInput.Key == KEY_KEY_S)
		{
			if(!m_keys[KEY_KEY_S])
			{
				m_keys[KEY_KEY_S] = true;
				m_car->setThrottlePercent(-100.0f);
			}
			else if(event.KeyInput.PressedDown == false)
			{
				m_keys[KEY_KEY_S] = false;
			}
		}
		if(event.KeyInput.Key == KEY_KEY_A)
		{
			if(!m_keys[KEY_KEY_A])
			{
				m_keys[KEY_KEY_A] = true;
				m_car->setSteeringPercent(-100.0f);
			}
			else if(event.KeyInput.PressedDown == false)
			{
				m_keys[KEY_KEY_A] = false;
			}
		}
		if(event.KeyInput.Key == KEY_KEY_D)
		{
			if(!m_keys[KEY_KEY_D])
			{
				m_keys[KEY_KEY_D] = true;
				m_car->setSteeringPercent(100.0f);
			}
			else if(event.KeyInput.PressedDown == false)
			{
				m_keys[KEY_KEY_D] = false;
			}
		}

		if(!m_keys[KEY_KEY_A] && !m_keys[KEY_KEY_D])
		{
			m_car->setSteeringPercent(0.0f);
		}

		if(!m_keys[KEY_KEY_W] && !m_keys[KEY_KEY_S])
		{
			m_car->setThrottlePercent(0.0f);
		}

		if(event.KeyInput.Key == KEY_ESCAPE)
		{
			device->closeDevice();
		}
	}

		return false;
	}
protected:
	IPhysicsCar* m_car;
	bool m_keys[KEY_KEY_CODES_COUNT];
};


int main()
{
	// start Irrlicht
	device = createDevice(EDT_OPENGL);

	// pointers to driver, scenemanager
	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();

	// add a light this time
	smgr->addLightSceneNode(0, vector3df(0,1000.0f,0));

	// create an FPS camera
	ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f);

	// move the camera up a bit so we can see the level
	camera->setPosition(vector3df(0, 200.0f, -30.0f));

	// start iphysics
	CPhysics physics;
	physics.init(device);
	
	cout << "1" << endl;

	SPhysicsCar carData;

	carData.carBodyOffset = vector3df(0, 0, 0);
	carData.carBodySize = vector3df(40, 16, 15);
	carData.carMass = 500.0f;
	carData.frontAxleOffset = carData.carBodySize.X * 0.48;
	carData.rearAxleOffset = carData.carBodySize.X * 0.48;
	carData.tireMass = 20.0f;
	carData.tireRadius = 16;
	carData.tireWidth = 10;
	carData.axleWidth = carData.carBodySize.Z + (2 * carData.tireWidth) + 10;
	carData.maxSteerAngle = 0.2f;
	carData.maxTorque = 1000.0f;
	carData.maxBrakes = 50.0f;

	carData.tireSuspensionLength = 0.2f;
	carData.tireSuspensionSpring = (carData.tireMass * 1.0f * 9.8f) / carData.tireSuspensionLength; 
	carData.tireSuspensionShock = sqrt(carData.tireSuspensionSpring) * 1.0f;

	carData.carBodyNode = smgr->addCubeSceneNode(1.0f);
	carData.carBodyNode->setScale(carData.carBodySize);

	carData.tireNode_FL = smgr->addSphereSceneNode(1.0f);
	carData.tireNode_FL->setScale(vector3df(carData.tireRadius, carData.tireRadius, carData.tireWidth));

	carData.tireNode_FR = smgr->addSphereSceneNode(1.0f);
	carData.tireNode_FR->setScale(vector3df(carData.tireRadius, carData.tireRadius, carData.tireWidth));

	carData.tireNode_RL = smgr->addSphereSceneNode(1.0f);
	carData.tireNode_RL->setScale(vector3df(carData.tireRadius, carData.tireRadius, carData.tireWidth));

	carData.tireNode_RR = smgr->addSphereSceneNode(1.0f);
	carData.tireNode_RR->setScale(vector3df(carData.tireRadius, carData.tireRadius, carData.tireWidth));

	//IPhysicsCar* car = physics.addCar(&carData);
	
	//car->setPosition(vector3df(100,200,100));
	
	// create our custom event receiver, pass a pointer to the car
//	CEventReceiver receiver(car);
//	device->setEventReceiver(&receiver);

	// create terrain from heightmap
	ITerrainSceneNode* terrainNode = smgr->addTerrainSceneNode("../../media/heightmap.bmp");
	terrainNode->setMaterialTexture(0, driver->getTexture("../../media/terrain_texture.jpg"));
	terrainNode->setMaterialTexture(1, driver->getTexture("../../media/terrain_detail.jpg"));
	terrainNode->setMaterialType(EMT_DETAIL_MAP);
	terrainNode->scaleTexture(1.0f, 10.0f);
	terrainNode->setMaterialFlag(EMF_LIGHTING, false);

	// create SPhysicsTerrain
	SPhysicsTerrain terrain;
	terrain.node = terrainNode;
	terrain.scale = vector3df(20.0f, 2.0f, 20.0f);

	// create Terrain entity
//	IPhysicsEntity* terrainEntity = physics.addEntity(&terrain);

	cout << "2" << endl;

	stringw caption;
	while(device->run())
	{
		driver->beginScene(true, true, SColor(0,100,100,100));

		caption = driver->getFPS();
		device->setWindowCaption(caption.c_str());

		smgr->drawAll();

		physics.update();
 
		driver->endScene();

	}

	physics.close();

	return 0;
}