#include "weapon.h"	

HandOfGod::HandOfGod(IKernel* kernel, IDirector* director, IScene* scene)
{
	Kernel = kernel;
	Director = director;
	Scene = scene;

	// Hand Setup..

	Hand = Director->AddXModel(Scene, "Content\\arm\\arm_right.x");
	Hand->Scale = Vector3<float>(0.3f, 0.3f, 0.3f);

	Flash = NULL;

	ITexture* FlashTexture = Director->CreateTexture("Content\\arm\\muzzle.png");

	FlashPrimary = Director->AddPlane(Scene, 1.0f, 1.0f);
	FlashPrimary->ApplyTexture(FlashTexture);
	FlashPrimary->Scale = Vector3<float>(0.0f, 0.0f, 0.0f);
	FlashPrimary->SetTechnique("Basic");

	Flash = new PointLight();
	Flash->Enabled = false;
	Flash->Ambient = Color(0.2f, 0.7f, 1.0f, 1.0f);
	Flash->Diffuse = Color(0.2f, 0.7f, 1.0f, 1.0f);
	Flash->Specular = Color(1.0f, 1.0f, 1.0f, 1.0f);
	Flash->Radius = 30.0f;

	Director->AddLight(Scene, Flash);

	// Properties..

	SwingPower = 0.02f;
	SmoothingPower = 0.96f;
	RecoilMax = 2.0f;
	YawRotation = 0.0f;
	PitchRotation = 0.0f;
	RecoilFactor = 0.0f;
	IsFiring = false;
	HolsterPosition = Vector3<float>(-2.5f, -2.5f, -0.5f);
	HolsterOffset = HolsterPosition;

	IsActive = false;
	IsHolstered = true;
	IsSwitching = false;
}

HandOfGod::~HandOfGod() { }

void HandOfGod::Fire()
{
	if (BlockFiring)
		return;

	FlashPrimary->Scale = Vector3<float>(2.5f, 2.5f, 2.5f);
	FlashRotationOffset = rand() * Kernel->GetFrameIndex();

	IsFiring = true;
	BlockFiring = true;

	ISceneNode* box = Director->AddBox(Scene, 2.0f, 2.0f, 2.0f);
	Vector3<float> cameraDir = Scene->GetActiveCamera()->GetDirection();
	box->Position = Scene->GetActiveCamera()->Position + (cameraDir * 20.0f);
	Flash->Position = box->Position;
}

void HandOfGod::Update(ICamera* camera)
{
	if (!IsActive && IsHolstered)
		Hand->AllowRender = false;
	else
		Hand->AllowRender = true;

	if (!IsActive && IsHolstered)
		return;

	if (camera->YawDelta > 0.0f)
		YawRotation += SwingPower;
	else if (camera->YawDelta < 0.0f)
		YawRotation -= SwingPower;

	YawRotation *= SmoothingPower;

	if (camera->PitchDelta > 0.0f)
		PitchRotation += SwingPower;
	else if (camera->PitchDelta < 0.0f)
		PitchRotation -= SwingPower;

	PitchRotation *= SmoothingPower;

	if (IsFiring)
	{
		Flash->Enabled = true;
		RecoilFactor += 0.3f;

		if (camera->Pitch < BSTM_PI_OVER_2)
			camera->Pitch += 0.01f;
	}
	else
	{
		Flash->Enabled = false;
		RecoilFactor *= 0.97f;
	}

	if (RecoilFactor >= RecoilMax)
	{
		IsFiring = false;
		BlockFiring = true;
	}

	if (RecoilFactor <= 0.5f)
		BlockFiring = false;

	BreathingFactor = sinf(Kernel->GetFrameIndex() / 800.0f) / 5.0f;

	if (camera->Velocity.Length() != 0.0f)
		BreathingFactor += sinf(Kernel->GetFrameIndex() / 90.0f) / 6.0f;

	Matrix4<float> lookTransforms = GetLookTransform(camera);

	Hand->World = GetWorldTransform(lookTransforms, 
		Vector3<float>(2.0f, -0.5f, -2.4f),
		Vector3<float>(1.7f, -0.3f + YawRotation, -0.2f + (PitchRotation / 2.0f)),
		Vector3<float>(0.3f, 0.3f, 0.3f));

	FlashPrimary->World = GetWorldTransform(lookTransforms, 
		Vector3<float>(3.0f, 0.5f, -2.0f),
		Vector3<float>(0.0f, BSTM_PI_OVER_2, 0.0f),
		FlashPrimary->Scale);

	Matrix4<float> finalFlashSpin;
	finalFlashSpin.SetRotationRadians(Vector3<float>(0.0f, 0.0f, FlashRotationOffset));

	FlashPrimary->World *= finalFlashSpin;

	Vector3<float> flashMinorPosition = Vector3<float>(9.0f,
		PitchRotation * 2.0f, 
		-2.0f - (YawRotation * 5.0f));

	if(FlashPrimary->Scale.Length() > 0.0f)
		FlashPrimary->Scale *= 0.7f;
}

AK47U::AK47U(IKernel* kernel, IDirector* director, IScene* scene)
{
	Kernel = kernel;
	Director = director;
	Scene = scene;

	// Gun Setup..

	Gun = Director->AddXModel(Scene, "Content\\ak47u\\ak47u.x");
	Gun->Scale = Vector3<float>(0.01f, 0.01f, 0.01f);
	Gun->Position = Vector3<float>(0.0f,8.0f,-10.0f);

	// Arm Setup..

	LeftArm = Director->AddXModel(Scene, "Content\\arm\\arm_left.x");
	LeftArm->Scale = Vector3<float>(0.3f, 0.3f, 0.3f);

	RightArm = Director->AddXModel(Scene, "Content\\arm\\arm_right.x");
	RightArm->Scale = Vector3<float>(0.3f, 0.3f, 0.3f);

	Gun->AllowFrustumCulling = false;
	LeftArm->AllowFrustumCulling = false;
	RightArm->AllowFrustumCulling = false;

	// Muzzle Flash Setup..

	ITexture* FlashTexture = Director->CreateTexture("Content\\ak47u\\muzzle.png");

	FlashPrimary = Director->AddPlane(Scene, 1.0f, 1.0f);
	FlashPrimary->ApplyTexture(FlashTexture);

	FlashHori = Director->AddPlane(Scene, 1.0f, 1.0f);
	FlashHori->ApplyTexture(FlashTexture);

	FlashVert = Director->AddPlane(Scene, 1.0f, 1.0f);
	FlashVert->ApplyTexture(FlashTexture);

	FlashPrimary->Scale = Vector3<float>(0.0f, 0.0f, 0.0f);
	FlashHori->Scale = Vector3<float>(0.0f, 0.0f, 0.0f);
	FlashVert->Scale = Vector3<float>(0.0f, 0.0f, 0.0f);

	FlashPrimary->SetTechnique("Basic");
	FlashHori->SetTechnique("Basic");
	FlashVert->SetTechnique("Basic");

	// Lights..

	Flash = new PointLight();
	Flash->Position = Vector3<float>(0.0f, 0.0f, 0.0f);
	Flash->Ambient = Color(1.0f, 1.0f, 1.0f, 1.0f);
	Flash->Diffuse = Color(1.0f, 0.7f, 0.2f, 1.0f);
	Flash->Specular = Color(1.0f, 1.0f, 1.0f, 1.0f);
	Flash->Radius = 30.0f;

	Director->AddLight(Scene, Flash);

	// Properties..

	SwingPower = 0.006f;
	SmoothingPower = 0.96f;
	RecoilMax = 1.0f;
	YawRotation = 0.0f;
	PitchRotation = 0.0f;
	RecoilFactor = 0.0f;
	IsFiring = false;
	HolsterPosition = Vector3<float>(-2.5f, -2.5f, -0.5f);
	HolsterOffset = HolsterPosition;

	IsActive = false;
	IsHolstered = true;
	IsSwitching = false;
}

AK47U::~AK47U() { }

void AK47U::Fire()
{
	if (BlockFiring)
		return;

	FlashPrimary->Scale = Vector3<float>(2.5f, 2.5f, 2.5f);
	FlashRotationOffset = rand() * Kernel->GetFrameIndex();

	FlashHori->Scale = Vector3<float>(4.0f, 1.5f, 3.0f);
	FlashVert->Scale = Vector3<float>(4.0f, 1.5f, 3.0f);

	IsFiring = true;
	BlockFiring = true;
}

void AK47U::Update(ICamera* camera)
{
	if (!IsActive && IsHolstered)
	{
		Gun->AllowRender = false;
		LeftArm->AllowRender = false;
		RightArm->AllowRender = false;
		FlashPrimary->AllowRender = false;
		FlashHori->AllowRender = false;
		FlashVert->AllowRender = false;
	}
	else
	{
		Gun->AllowRender = true;
		LeftArm->AllowRender = true;
		RightArm->AllowRender = true;
		FlashPrimary->AllowRender = true;
		FlashHori->AllowRender = true;
		FlashVert->AllowRender = true;
	}

	if (!IsActive && IsHolstered)
		return;

	if (camera->YawDelta > 0.0f)
		YawRotation += SwingPower;
	else if (camera->YawDelta < 0.0f)
		YawRotation -= SwingPower;

	YawRotation *= SmoothingPower;

	if (camera->PitchDelta > 0.0f)
		PitchRotation += SwingPower;
	else if (camera->PitchDelta < 0.0f)
		PitchRotation -= SwingPower;

	PitchRotation *= SmoothingPower;

	if (IsFiring)
	{
		Flash->Enabled = true;

		RecoilFactor += 1.0f;

		if (camera->Pitch < BSTM_PI_OVER_2)
			camera->Pitch += 0.02f;
	}
	else
	{
		Flash->Enabled = false;
		RecoilFactor *= 0.8f;
	}

	if (RecoilFactor >= RecoilMax)
	{
		IsFiring = false;
		BlockFiring = true;
	}

	if (RecoilFactor <= 0.5f)
		BlockFiring = false;

	BreathingFactor = sinf(Kernel->GetFrameIndex() / 1200.0f) / 6.0f;

	if (camera->Velocity.Length() != 0.0f)
		BreathingFactor += sinf(Kernel->GetFrameIndex() / 90.0f) / 6.0f;

	Matrix4<float> lookTransforms = GetLookTransform(camera);

	Gun->World = GetWorldTransform(lookTransforms, 
		Vector3<float>(2.0f, -1.4f, -2.0f), ///
		Vector3<float>(0.0f, YawRotation, PitchRotation),
		Vector3<float>(0.01f, 0.01f, 0.01f));

	FlashPrimary->World = GetWorldTransform(lookTransforms, 
		Vector3<float>(7.5f, PitchRotation * 2.0f, -2.0f - (YawRotation * 5.0f)),
		Vector3<float>(0.0f, BSTM_PI_OVER_2, 0.0f),
		FlashPrimary->Scale);

	Matrix4<float> finalFlashSpin;
	finalFlashSpin.SetRotationRadians(Vector3<float>(0.0f, 0.0f, FlashRotationOffset));

	FlashPrimary->World *= finalFlashSpin;

	Vector3<float> flashMinorPosition = Vector3<float>(9.0f,
		PitchRotation * 2.0f, 
		-2.0f - (YawRotation * 5.0f));

	FlashHori->World = GetWorldTransform(lookTransforms, 
		flashMinorPosition,
		Vector3<float>(0.0f, 0.0f, 0.0f),
		FlashHori->Scale);

	FlashVert->World = GetWorldTransform(lookTransforms,  
		flashMinorPosition,
		Vector3<float>(BSTM_PI_OVER_2, 0.0f, 0.0f),
		FlashVert->Scale);

	LeftArm->World = GetWorldTransform(lookTransforms, 
		Vector3<float>(2.75f, -0.7f, -1.55f - YawRotation),
		Vector3<float>(0.4f, YawRotation - 0.9f, PitchRotation * 1.5f),
		Vector3<float>(0.3f, 0.3f, 0.3f));

	RightArm->World = GetWorldTransform(lookTransforms, 
		Vector3<float>(-0.2f, -1.0f, -2.2f + YawRotation),
		Vector3<float>(0.0f, -1.5f, -PitchRotation),
		Vector3<float>(0.3f, 0.3f, 0.3f));

	Flash->Position = camera->Position + Vector3<float>(-5.0f, 0.0f, -5.0f);

	if(FlashPrimary->Scale.Length() > 0.0f)
		FlashPrimary->Scale = Vector3<float>(0.0f,0.0f,0.0f);

	if(FlashHori->Scale.Length() > 0.0f)
		FlashHori->Scale = Vector3<float>(0.0f,0.0f,0.0f);

	if(FlashVert->Scale.Length() > 0.0f)
		FlashVert->Scale = Vector3<float>(0.0f,0.0f,0.0f);
		
}