#include "GameState.h"
#include "DllInterfaces/GFXAPI.h"
#include <Protocols.h>
#include "NetworkClient.h"
#include "Camera_FPSV2.h"
#include <GameServerAPI.h>
#include "C_Light.h"
#include "C_obj/C_Player.h"
#include "C_obj/C_DynamicObj.h"
#include "C_obj/C_StaticObj.h"
#include "Utilities.h"
#include "GamingUI.h"
#include "RespawnUI.h"
#include "StatsUI.h"
#include <ObjectDefines.h>

using namespace ::DanBias::Client;
using namespace ::Oyster;
using namespace ::Oyster::Network;
using namespace ::Oyster::Math3D;
using namespace ::GameLogic;
using namespace ::Utility::DynamicMemory;
using namespace ::Utility::String;
using namespace ::Utility::Value;

struct  GameState::MyData
{
	MyData(){}
	GameClientState::ClientState nextState;
	NetworkClient *nwClient;
	::Input::Mouse *mouseInput;
	::Input::Keyboard *keyboardInput;

	::std::map<int, ::Utility::DynamicMemory::UniquePointer<::DanBias::Client::C_StaticObj>> *staticObjects;
	::std::map<int, ::Utility::DynamicMemory::UniquePointer<::DanBias::Client::C_DynamicObj>> *dynamicObjects;
	::std::map<int, ::Utility::DynamicMemory::UniquePointer<::DanBias::Client::C_Light>> *lights;

	//C_Player player;
	::std::map<int, ::Utility::DynamicMemory::UniquePointer<::DanBias::Client::C_Player>> players;
	Camera_FPSV2 camera;

	int myId;

} privData;

inline Quaternion ArrayToQuaternion( const float source[4] )
{
	return Quaternion( Float3(source[0], source[1], source[2]), source[3] );
}

GameState::GameState()
{
	this->privData = nullptr;
}

GameState::~GameState()
{
	if( this->privData )
		this->Release();
}

bool GameState::Init( SharedStateContent &shared )
{
	// we may assume that shared.network is properly connected
	// and there is content in shared.dynamicObjects and shared.staticObjects

	this->privData = new MyData();

	this->privData->nextState = GameClientState::ClientState_Same;
	this->privData->nwClient = shared.network;
	this->privData->mouseInput = shared.mouseDevice;
	this->privData->keyboardInput = shared.keyboardDevice;
	this->privData->staticObjects = &shared.staticObjects;
	this->privData->dynamicObjects = &shared.dynamicObjects;
	this->privData->lights = &shared.lights;

	Graphics::API::Option gfxOp = Graphics::API::GetOption();
	Float aspectRatio = gfxOp.Resolution.x / gfxOp.Resolution.y;
	this->privData->camera.SetPerspectiveProjection( Utility::Value::Radian(90.0f), aspectRatio, 0.1f, 1000.0f );
	Graphics::API::SetProjection( this->privData->camera.GetProjectionMatrix() );
	gfxOp.AmbientValue = 0.5f;
	gfxOp.GlobalGlowTint = Math::Float3(1,1,1);
	gfxOp.GlobalTint = Math::Float3(1,1,1);
	Graphics::API::SetOptions(gfxOp);

	// DEGUG KEYS
	this->key_Reload_Shaders = false;
	this->key_Wireframe_Toggle = false;
	this->renderWhireframe = false;
	// !DEGUG KEYS

	shared.keyboardDevice->ReleaseTextTarget();
	//shared.mouseDevice->AddMouseEvent(this);

	auto light = this->privData->lights->begin();
	for( ; light != this->privData->lights->end(); ++light )
	{
		light->second->Render();
	}

	// create UI states
	this->gameUI = new GamingUI(&shared, &this->privData->camera);
	this->respawnUI = new RespawnUI(this->privData->nwClient, 20);
	this->statsUI = new StatsUI();
	this->currGameUI = gameUI; 
	((GamingUI*)gameUI)->Init();
	((RespawnUI*)respawnUI)->Init();
	((StatsUI*)statsUI)->Init();

	//tell server ready
	this->privData->nwClient->Send( Protocol_General_Status(Protocol_General_Status::States_ready) );

	return true;
}

void GameState::InitiatePlayer( int id, const std::string &modelName, const float position[3], const float rotation[4], const float scale[3], bool isMyPlayer )
{
	ModelInitData modelData;
	modelData.visible	= true;
	modelData.position	= position;
	modelData.rotation	= ArrayToQuaternion( rotation );
	modelData.scale		= scale;
	modelData.id		= id;
	StringToWstring(modelName,modelData.modelPath);

	// RB DEBUG
	RBInitData RBData;
	RBData.position = position;
	RBData.rotation = ArrayToQuaternion( rotation );
	RBData.scale =  scale;
	RBData.type = RB_Type_Cube;
	// !RB DEBUG 
	C_Player *p = new C_Player();
	if( p->Init(modelData) )
	{
		// RB DEBUG
		p->InitRB( RBData );
		// !RB DEBUG 
		// start with runing animation
		p->playAnimation( L"idle", true );

		(this->privData->players)[id] = p;
		
		if( isMyPlayer )
		{
			this->privData->myId = id;
			this->privData->camera.SetPosition( p->getPos() );
			Float3 offset = Float3( 0.0f );
			// DEBUG position of camera so we can see the player model
			//offset.y = p->getScale().y * 5.0f;
			//offset.z = p->getScale().z * -5.0f;
			// !DEBUG
			//this->privData->camera.SetHeadOffset( offset );
			//this->privData->camera.UpdateOrientation();
		}
	}
	else
	{
		int i = 0; 
		// some error loading model 
	}
}

GameClientState::ClientState GameState::Update( float deltaTime )
{
	GameStateUI::UIState UIstate = this->gameUI->Update( deltaTime );
	switch (UIstate)
	{
	case DanBias::Client::GameStateUI::UIState_shut_down:
		{
			this->privData->nextState = ClientState_Quit;
			// disconnect 
		}
	
		break;
	case DanBias::Client::GameStateUI::UIState_same:
		break;
	case DanBias::Client::GameStateUI::UIState_gaming:
		break;
	case DanBias::Client::GameStateUI::UIState_main_menu:
		{
			this->privData->nextState = ClientState_Main;
			// disconnect 
		}
		
		break;
	
	default:
		break;
	} 
	// DEBUG keybindings
	ReadKeyInput();

	return this->privData->nextState;
}

bool GameState::Render()
{
	Oyster::Graphics::API::SetView( this->privData->camera.GetViewMatrix() );

	Oyster::Graphics::API::NewFrame();

	// for debugging to be replaced with render weapon
	auto playerObject = this->privData->players.begin();
	for( ; playerObject != this->privData->players.end(); ++playerObject )
	{
		if(playerObject->second)
		{
			if( this->privData->myId != playerObject->second->GetId() )
			{
				playerObject->second->Render();
			}
		}
	}

	auto staticObject = this->privData->staticObjects->begin();
	for( ; staticObject != this->privData->staticObjects->end(); ++staticObject )
	{
		staticObject->second->Render();
	}

	auto dynamicObject = this->privData->dynamicObjects->begin();
	for( ; dynamicObject != this->privData->dynamicObjects->end(); ++dynamicObject )
	{
		if( dynamicObject->second )
		{
			dynamicObject->second->Render();

		}
	}

#ifdef _DEBUG //RB DEBUG render wire frame 
		if(this->renderWhireframe)
		{
			Oyster::Graphics::API::StartRenderWireFrame();

			playerObject = this->privData->players.begin();
			for( ; playerObject != this->privData->players.end(); ++playerObject )
			{
				if(playerObject->second)
				{
					if( playerObject->second->getBRtype() == RB_Type_Cube)
					{
						Oyster::Graphics::API::RenderDebugCube( playerObject->second->getRBWorld());
					}
					if( playerObject->second->getBRtype() == RB_Type_Sphere)
					{
						Oyster::Graphics::API::RenderDebugSphere( playerObject->second->getRBWorld());
					}
				}
			}

			staticObject = this->privData->staticObjects->begin();
			for( ; staticObject != this->privData->staticObjects->end(); ++staticObject )
			{
				if( staticObject->second->getBRtype() == RB_Type_Cube)
				{
					Oyster::Graphics::API::RenderDebugCube( staticObject->second->getRBWorld());
				}
				if( staticObject->second->getBRtype() == RB_Type_Sphere)
				{
					Oyster::Graphics::API::RenderDebugSphere( staticObject->second->getRBWorld());
				}
			}

			dynamicObject = this->privData->dynamicObjects->begin();
			for( ; dynamicObject != this->privData->dynamicObjects->end(); ++dynamicObject )
			{
				if( dynamicObject->second )
				{
					if( dynamicObject->second->getBRtype() == RB_Type_Cube)
					{
						Oyster::Graphics::API::RenderDebugCube( dynamicObject->second->getRBWorld());
					}
					if( dynamicObject->second->getBRtype() == RB_Type_Sphere)
					{
						Oyster::Graphics::API::RenderDebugSphere( dynamicObject->second->getRBWorld());
					}
				}
			}
		}
#endif //!RB DEBUG 

	Oyster::Graphics::API::StartGuiRender();
	// render gui elemnts
	if(currGameUI->HaveGUIRender())
		currGameUI->RenderGUI();
	if(renderStats)
	{	
		if(statsUI->HaveGUIRender())
			statsUI->RenderGUI();
	}
	Oyster::Graphics::API::StartTextRender();
	if(currGameUI->HaveTextRender())
		currGameUI->RenderText();
	if(renderStats)
	{	
		if(statsUI->HaveTextRender())
			statsUI->RenderText();
	}

	Oyster::Graphics::API::EndFrame();
	return true;
}

bool GameState::Release()
{
	Graphics::API::Option o = Graphics::API::GetOption();
	if( privData )
	{
		auto playerObject = this->privData->players.begin();
		for( ; playerObject != this->privData->players.end(); ++playerObject )
		{
			playerObject->second = nullptr;
		}

		auto staticObject = this->privData->staticObjects->begin();
		for( ; staticObject != this->privData->staticObjects->end(); ++staticObject )
		{
			staticObject->second = nullptr;
		}

		auto dynamicObject = this->privData->dynamicObjects->begin();
		for( ; dynamicObject != this->privData->dynamicObjects->end(); ++dynamicObject )
		{
			dynamicObject->second = nullptr;
		}

		auto light = this->privData->lights->begin();
		for( ; light != this->privData->lights->end(); ++light )
		{
			light->second->Render();
		}

		this->privData->staticObjects->clear();
		this->privData->dynamicObjects->clear();
		this->privData->lights->clear();

		privData = NULL;
	}

	if(respawnUI) 
	{
		respawnUI->Release();
		delete respawnUI;
		respawnUI = NULL;
	}
	
	if(gameUI)
	{
		gameUI->Release();
		delete gameUI;
		gameUI = NULL;
	}
	if(statsUI)
	{
		statsUI->Release();
		delete statsUI;
		statsUI = NULL;
	}
	currGameUI = NULL;
	
	return true;
}

void GameState::ChangeState( ClientState next )
{
	this->privData->nextState = next;
}

void GameState::ReadKeyInput()
{
#ifdef _DEBUG // DEGUG KEYS

	// Reload shaders
	if( this->privData->keyboardInput->IsKeyDown(::Input::Enum::SAKI_R) )
	{
		if( !this->key_Reload_Shaders )
		{

			Graphics::API::ReloadShaders();

			this->key_Reload_Shaders = true;
		}
	} 
	else 
		this->key_Reload_Shaders = false;

	// toggle wire frame render
	if( this->privData->keyboardInput->IsKeyDown(::Input::Enum::SAKI_T) )
	{
		if( !this->key_Wireframe_Toggle )
		{
			this->renderWhireframe = !this->renderWhireframe;
			this->key_Wireframe_Toggle = true;
			// DEBUG set you as dead when render wireframe
			this->currGameUI = respawnUI;
			// !DEBUG
		}
	} 
	else 
	{
		this->key_Wireframe_Toggle = false;
		// DEBUG set you as dead when render wireframe
		this->currGameUI = gameUI;
		// !DEBUG
	}
#endif // !DEGUG KEYS

	// toggle wire frame render
	if( this->privData->keyboardInput->IsKeyDown(::Input::Enum::SAKI_Tab) )
	{
		if( !this->key_showStats )
		{
			this->renderStats = true;
			this->key_showStats = true;
		}
	} 
	else 
	{
		this->renderStats = false;
		this->key_showStats = false;
	}
}


const GameClientState::NetEvent & GameState::DataRecieved( const GameClientState::NetEvent &message )
{
	if( message.args.type == NetworkClient::ClientEventArgs::EventType_ProtocolFailedToSend )
	{ // TODO: Reconnect
		const char *breakpoint = "temp trap";
		this->privData->nwClient->Disconnect();
		this->ChangeState( GameClientState::ClientState_Main );
	}

	// fetching the id data.
	short ID = message.args.data.protocol[0].value.netShort;

	if( ProtocolIsGameplay(ID) )
	{
		CustomNetProtocol data = message.args.data.protocol;

		switch(ID)
		{
		case protocol_Gameplay_ObjectPickup:	
			{
				Protocol_ObjectPickup decoded(data);
				decoded.object_ID;
				C_Object *object; 
				object = (this->privData->players)[decoded.object_ID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.object_ID];
				}

				if( object )
				{
					if( this->privData->myId == decoded.object_ID )
					{
						 // I picked up the pickUp!
					}

					if (decoded.pickup_ID == GameLogic::PickupType::PickupType_Health)
					{
						// object->PickupHealth();
					}
					else if (decoded.pickup_ID == GameLogic::PickupType::PickupType_SpeedBoost)
					{
						// object->PickupSpeed();
					}
				}
				decoded.pickup_ID;
				
				
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectDamage:			
			{
				Protocol_ObjectDamage decoded(data);
				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];
				}

				if( object )
				{
					if( this->privData->myId == decoded.objectID )
					{
						// show that you took dmg
						if(currGameUI == gameUI)
						{
							// set given players HP 
							((GamingUI*)currGameUI)->SetHPtext(std::to_wstring(decoded.healthLost));
						}
					}
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectHealthStatus:		
			{ 
				// don't know if needed
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectPosition:
			{
				Protocol_ObjectPosition decoded(data);

				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];
				}

				if( object )
				{
					if( this->privData->myId == decoded.objectID )
					{
						this->privData->camera.SetPosition( decoded.position );
					}

					object->setPos( decoded.position );
					// RB DEBUG 
					object->setRBPos ( decoded.position );  
					// !RB DEBUG 
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectScale:
			{
				Protocol_ObjectScale decoded(data);
				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];
				}

				if( object )
				{
					object->setScale( decoded.scale );
					// RB DEBUG 
					object->setRBScale ( decoded.scale );  
					// !RB DEBUG 
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectRotation:
			{
				Protocol_ObjectRotation decoded(data);
				Quaternion rotation = Quaternion( Float3(decoded.rotationQ), decoded.rotationQ[3] );
				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];
				}

				if( object )
				{
					if( this->privData->myId == decoded.objectID )
					{
						this->privData->camera.SetRotation( rotation );
					}

					object->setRot( rotation );
					// RB DEBUG 
					object->setRBRot( rotation );  
					// !RB DEBUG 
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectPositionRotation:
			{
				Protocol_ObjectPositionRotation decoded(data);
				Float3 position = decoded.position;
				Quaternion rotation = Quaternion( Float3(decoded.rotationQ), decoded.rotationQ[3] );
				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];
				}

				if( object )
				{
					if( this->privData->myId == decoded.objectID )
					{
						this->privData->camera.SetPosition( position );
						this->privData->camera.SetRotation( rotation );
					}
					object->setPos( position );
					object->setRot( rotation );
					object->updateWorld();
					// RB DEBUG 
					object->setRBPos ( position );  
					object->setRBRot ( rotation );  
					object->updateRBWorld();
					// !RB DEBUG 
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectEnabled:	
			{
				Protocol_ObjectEnable decoded(data);
				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];

					if(!object)
					{
						//If it is a static object
						object = (*this->privData->staticObjects)[decoded.objectID];
					}
				}

				if( object )
				{
					 object->SetVisible(true);
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectDisabled:
			{
				Protocol_ObjectDisable decoded(data);
				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];
					
					if(!object)
					{
						//If it is a static object
						object = (*this->privData->staticObjects)[decoded.objectID];
					}
				}

				if( object )
				{
					object->SetVisible(false);
				}

				/*auto object = this->privData->dynamicObjects->find( decoded.objectID );
				if( object != this->privData->dynamicObjects->end() )
				{
				object->second = nullptr;
				this->privData->dynamicObjects->erase( object );
				}*/

			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectCreate:
			{
				Protocol_ObjectCreate decoded(data);
				C_DynamicObj* object = new C_DynamicObj();

				ModelInitData modelData;
				{
					modelData.position = Float3( decoded.position );
					modelData.rotation = Quaternion( Float3(decoded.position), decoded.rotationQ[3] );
					modelData.scale = Float3( decoded.scale );
					modelData.visible = true;
					modelData.id = decoded.objectID;

					::Utility::String::StringToWstring( decoded.name, modelData.modelPath );
				}
				object->Init(modelData);
				// RB DEBUG
				// Is just using the model position since the rigid body data should never be sent to the client 
				RBInitData RBData;
				RBData.position = decoded.position;
				RBData.rotation = ArrayToQuaternion( decoded.position );
				RBData.scale =  Float3( decoded.scale );

				object->InitRB( RBData );
				// !RB DEBUG 

				(*this->privData->dynamicObjects)[decoded.objectID] = object;

			}		
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectCreatePlayer:
			{
				Protocol_ObjectCreatePlayer decoded(data);
				this->InitiatePlayer( decoded.objectID, decoded.meshName, decoded.position, decoded.rotationQ, decoded.scale, decoded.owner );				
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectJoinTeam:			break; /** @todo TODO: implement */
		case protocol_Gameplay_ObjectLeaveTeam:			break; /** @todo TODO: implement */
		case protocol_Gameplay_ObjectWeaponCooldown:	break; /** @todo TODO: implement */
		case protocol_Gameplay_ObjectWeaponEnergy:		break; /** @todo TODO: implement */
		case protocol_Gameplay_ObjectRespawn:	
			{
				Protocol_ObjectRespawn decoded(data);
				
				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];
				}

				if( object )
				{
					if( this->privData->myId == decoded.objectID )
					{
						this->privData->camera.SetPosition( decoded.position );
					}
					object->setPos( decoded.position );
					object->updateWorld();
					// RB DEBUG 
					object->setRBPos ( decoded.position );  
					object->updateRBWorld();
					// !RB DEBUG 
				}
				this->currGameUI =  this->gameUI;
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectDie:
			{
				Protocol_ObjectDie decoded(data);
				// if is this player. Remember to change camera
				int killerID = decoded.killerID;
				int victimID = decoded.objectID;
				if( this->privData->myId == decoded.objectID )
				{
					this->currGameUI =  this->respawnUI;
					// set countdown 
					((RespawnUI*)currGameUI)->SetCountdown( decoded.seconds );
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectDisconnectPlayer:
			{
				//Remove the disconnected player
				Protocol_ObjectDisconnectPlayer decoded(data);
				C_Player *player; 
				player = (this->privData->players)[decoded.objectID];

				if( player )
				{
					if( this->privData->myId == decoded.objectID )
					{
						// dont delete my player
					}
					if( player )
					{
						player->SetVisible(false);
						(this->privData->players)[decoded.objectID].Release();
					}
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectAction:
			{
				Protocol_ObjectAction decoded(data);

				C_Player *player; 
				player = (this->privData->players)[decoded.objectID];
				
				if( player )
				{
					if( this->privData->myId == decoded.objectID )
					{
						// my player animation
					//}
					//else
					//{
						// HACK for now animate my char
						switch (decoded.animationID)
						{
						case  GameLogic::PlayerAction::PlayerAction_Walk:
							player->playAnimation(L"run_forwards", true);
							break;
						case GameLogic::PlayerAction::PlayerAction_Jump:
							player->playAnimation(L"movement", true);
							break;
						case GameLogic::PlayerAction::PlayerAction_Idle:
							player->playAnimation(L"idle", true);
							break;

						case GameLogic::WeaponAction::WeaponAction_PrimaryShoot:
							break;
						case GameLogic::WeaponAction::WeaponAction_SecondaryShoot:
							break;
						case GameLogic::WeaponAction::WeaponAction_Reload:
							break;


						default:
							break;
						}
					}
				}
			}
			return GameClientState::event_processed;
		case protocol_Gameplay_ObjectCollision:
			{
				Protocol_ObjectCollision decoded(data);
				C_Object *object; 
				object = (this->privData->players)[decoded.objectID];
				if( !object)
				{
					// if it is not a player 
					object = (*this->privData->dynamicObjects)[decoded.objectID];
				}
				if( object )
				{
					switch (decoded.collisionID)
					{
					case GameLogic::CollisionEvent::CollisionEvent_BasicCollision:
						break;
					default:
						break;
					}
				}
			}
			return GameClientState::event_processed;
		default: break;
		}
	}
	else if( ProtocolIsGeneral(ID) )
	{
		switch( ID )
		{
			case protocol_General_Status:				break; /** @todo TODO: implement */
			case protocol_General_Text:					break; /** @todo TODO: implement */
		default: break;
		}
	}

	return message;
}

/* :HACK! */
// TODO: Fix camera movement on client
/*
void GameState::SetUp( DanBias::Client::C_Player* p)
{
	Float3 up;
	auto it = this->privData->staticObjects->begin();
	for (it; it != this->privData->staticObjects->end(); it++)
	{
		if(it->second->GetGameObjectType() == GameLogic::ObjectSpecialType_World)
		{
			up = - (p->getPos() - it->second->getPos());
			break;
		}
	}
	
	Quaternion newRotation;

	Float3 v1 = this->privData->camera.GetUp();
	Float3 v2(up.x, up.y, up.z);

	Quaternion q;
	Float3 a = v1.Cross(v2);
	
	if (v1.Dot(v2) < -0.999999) 
	{
		Float3 xCrossPre = Float3(1, 0 ,0).Cross(v1);
		if(xCrossPre.GetLength() < 0.000001)
			xCrossPre = Float3(0, 1 ,0).Cross(v1);
		xCrossPre.Normalize();
		
		//q.setRotation(xCrossPre, 3.1415);
    }
	else if (v1.Dot(v2) > 0.999999) 
	{
           q = Quaternion(Float3(0.0f), 1);
	}
	else
	{
		q.imaginary.x = a.x;
		q.imaginary.y = a.y;
		q.imaginary.z = a.z;

		q.real = (1 + v1.Dot(v2));

		q.Normalize();
	}

	//Get Rotation from matrix
	//float trace = this->privData->camera..v[0].x + trans.v[1].y + trans.v[2].z;
	float trace = trans.v[0].x + trans.v[1].y + trans.v[2].z;

	float temp[4];

	if (trace > float(0.0)) 
	{
		float s = sqrt(trace + float(1.0));
		temp[3]=(s * float(0.5));
		s = float(0.5) / s;

		temp[0]=((trans.v[2].y - trans.v[1].z) * s);
		temp[1]=((trans.v[0].z - trans.v[2].x) * s);
		temp[2]=((trans.v[1].x - trans.v[0].y) * s);
	} 
	else 
	{
		int i = trans.v[0].x < trans.v[1].y ? 
			(trans.v[1].y < trans.v[2].z ? 2 : 1) :
			(trans.v[0].x < trans.v[2].z ? 2 : 0); 
		int j = (i + 1) % 3;  
		int k = (i + 2) % 3;

		float s = sqrt(trans.v[i][i] - trans.v[j][j] - trans.v[k][k] + float(1.0));
		temp[i] = s * float(0.5);
		s = float(0.5) / s;

		temp[3] = (trans.v[k][j] - trans.v[j][k]) * s;
		temp[j] = (trans.v[j][i] + trans.v[i][j]) * s;
		temp[k] = (trans.v[k][i] + trans.v[i][k]) * s;
	}
	Quaternion n = Quaternion(Float3(temp[0],temp[1],temp[2]),temp[3]);

	newRotation = q * n;
	this->privData->camera.SetRotation(newRotation);
}
void GameState::OnMouseMoveVelocity ( Input::Struct::SAIPointInt2D coordinate, Input::Mouse* sender )
{ 
	auto it = this->privData->players.begin();
	for (it; it != this->privData->players.end(); it++)
	{
		if(it->second->GetId() == this->privData->myId)
		{
			this->SetUp(it->second);
			return;
		}
	}
	
}
*/

