namespace BP
{
	namespace Weapon
	{
		const float FLYING_GUN_TIME_TO_REFIRE                   = 0.7f;
		const int   FLYING_GUN_MACHINE_GUN_REFIRE_ITERATION     = 15;
		
		class FlyingGun : ScriptWeapon
		{   
			int m_nWeaponSide;
			float m_fStompTime;
			//------------------------------------------------------------------------------------------------------------------------
			FlyingGun(kWeapon @actor)
			{
				id = kWpn_FlyingGun;
				super(actor);
				m_nWeaponSide = 1;
				m_fStompTime = 0;
			}
			//------------------------------------------------------------------------------------------------------------------------
			void OnBeginFire() override
			{
				ScriptWeapon::OnBeginFire();
				
				if (m_nWeaponSide > 0)
				{
					self.AnimTrackComponent().Blend(ANIM_WPN_FIRE_ARTILLERY_LEFT, 0, 8, 0);
				}
				else
				{
					self.AnimTrackComponent().Blend(ANIM_WPN_FIRE_ARTILLERY_RIGHT, 0, 8, 0);
				}
				
				m_nWeaponSide = -m_nWeaponSide;
			}
			//------------------------------------------------------------------------------------------------------------------------
			void OnEquipped() override
			{
				ScriptWeapon::OnEquipped();
				
				// if (self.GetTarget() is null || self.GetTarget().IsStale())
				// {
					// kParticle@ particle = BP::Spawn::Particle("particles/BP/HitTest.particle", self.Owner().Actor().CastToActor(), Math::vecZero);
					// self.SetTarget(@particle);
				// }
				
				kActor@ actor = self.Owner().Actor().CastToActor();
				actor.MovementComponent().Velocity() = Math::vecZero;
				// self.RenderMeshComponent().SetRotationOffset(3, Math::Deg2Rad(180.0f), 0, 0, 1);
				self.RenderMeshComponent().SetScale(3, Math::vecZero);
				//self.Scale() = kVec3(0.9f, 0.9f, 0.9f);
				//self.PlayLoopingSound("sounds/shaders/Cooky's Wind Loop.ksnd");
				//self.PlayLoopingSound("sounds/shaders/Wind Loop Fer Andy.ksnd");
				// self.PlayLoopingSound("sounds/shaders/Wind Loop Intro 1.ksnd");
				//self.PlayLoopingSound("sounds/shaders/City 2 Wind Gust 1.ksnd");
				self.PlayLoopingSound("sounds/shaders/BP/FlyingWind.ksnd");
			}
			//------------------------------------------------------------------------------------------------------------------------
			void OnLower()
			{
				self.StopLoopingSounds();
				// if (self.GetTarget() !is null && !self.GetTarget().IsStale())
				// {
					// self.GetTarget().Remove();
				// }
			}
			//------------------------------------------------------------------------------------------------------------------------
			bool CheckHit()
			{
				//change to up/down/left/right instead of corners
				
				kActor@ actor = self.Owner().Actor().CastToActor();
				uint cfFlags = uint(CF_POLYCOLLISION | CF_COLLIDEJOINTS | CF_EXPANDJOINTNODES | CF_NOBACKFACECULLING);
				// float rayLength = 40.0f;
				float pHeight = 50.0f;
				kVec3 rayStart = actor.Origin() + kVec3(0, 0, pHeight);
				// kVec3 rayDest = rayStart + BP::Actor::Forward(actor) * rayLength;
				// kQuat pQuat(actor.Pitch(), 0.0f, actor.Yaw());
				kClipInfo rayInfo;
				
				// float f = 2.0f; //forward amount
				// float r = 2.5f; //right amount
				// float u = 1.5f; //up amount
				float f = 60.0f; //forward amount
				float r = 75.0f; //right amount
				float u = 75.0f; //up amount
				kVec3 pos1 = rayStart + BP::Actor::Direction(actor, 0.0f, f, u); //top
				BP::Debug::Position(0, pos1, kVec3(0.2f, 0.2f, 0.2f));
				kVec3 pos2 = rayStart + BP::Actor::Direction(actor, 0.0f, f, -u); //bottom
				BP::Debug::Position(1, pos2, kVec3(0.2f, 0.2f, 0.2f));
				actor.WorldComponent().HitScan(rayInfo, pos1, pos2, cfFlags);
				BP::Debug::Ray(rayInfo);
				if (rayInfo.fraction < 1.0f)
				{
					return true;
				}
				// actor.WorldComponent().HitScan(rayInfo, pos2, pos1, cfFlags);
				// if (rayInfo.fraction < 1.0f)
				// {
					// return true;
				// }
				pos1 = rayStart + BP::Actor::Direction(actor, r, f, 0.0f); //right
				BP::Debug::Position(2, pos1, kVec3(0.2f, 0.2f, 0.2f));
				pos2 = rayStart + BP::Actor::Direction(actor, -r, f, 0.0f); //left
				BP::Debug::Position(3, pos2, kVec3(0.2f, 0.2f, 0.2f));
				actor.WorldComponent().HitScan(rayInfo, pos1, pos2, cfFlags);
				BP::Debug::Ray(rayInfo);
				if (rayInfo.fraction < 1.0f)
				{
					return true;
				}
				// actor.WorldComponent().HitScan(rayInfo, pos2, pos1, cfFlags);
				// if (rayInfo.fraction < 1.0f)
				// {
					// return true;
				// }
				

				return false;
			}
			kVec3 vel; //acceleration
			float velz;
			//------------------------------------------------------------------------------------------------------------------------
			void OnTick() override
			{
				ScriptWeapon::OnTick();
				kActor@ actor = self.Owner().Actor().CastToActor();

				if (CheckHit())
				{
					DebugLog("Hit Something " + actor.GameTicks());
				}

				
				// if (self.GetTarget() is null || self.GetTarget().IsStale())
				// {
					// DebugLog("Hit Something");
					// kParticle@ particle = BP::Spawn::Particle("particles/BP/HitTest.particle", actor, Math::vecZero);
					// self.SetTarget(@particle);
				// }
				// else
				// {
					// self.GetTarget().Origin() = BP::Actor::CenterOrigin(actor);// + actor.MovementComponent().Velocity() * 50.0f;
					// self.GetTarget().CastToParticle().Direction() = actor.MovementComponent().Velocity().Normalize();
					// self.GetTarget().CastToParticle().Velocity() = actor.MovementComponent().Velocity().Normalize();
					// //DebugLog(self.GetTarget().Origin().ToString() + " | " + self.Owner().Actor().CastToActor().Origin().ToString());
				// }

				float speed = 10.0f;
				float moveSpeed = 5.0f;
				// kVec3 minVel(-maxSpeed, -maxSpeed, -maxSpeed);
				// kVec3 maxVel(maxSpeed, maxSpeed, maxSpeed);
				
				kVec3 forwardDir = BP::Actor::Forward(@actor);
				kVec3 rightDir = BP::Actor::Right(@actor);
				vel.x = forwardDir.x * speed;
				vel.y = forwardDir.y * speed;
				vel.z = forwardDir.z * speed;
				if (BP::Input::Forward())
				{
					vel.x += forwardDir.x * moveSpeed;
					vel.y += forwardDir.y * moveSpeed;
				}
				else if (BP::Input::Backward())
				{
					vel.x -= forwardDir.x * moveSpeed;
					vel.y -= forwardDir.y * moveSpeed;
				}
				if (BP::Input::StrafeLeft())
				{
					vel.x -= rightDir.x * moveSpeed;
					vel.y -= rightDir.y * moveSpeed;
				}
				else if (BP::Input::StrafeRight())
				{
					vel.x += rightDir.x * moveSpeed;
					vel.y += rightDir.y * moveSpeed;
				}
				
				//set a force move direction and limit yaw to -90..90 of force move direction
				//Event.RunAction(self, null, ACTION_UNBLOCK, Math::vecZero);
				
				actor.Yaw() = Math::Clampf(actor.Yaw(), Math::Deg2Rad(60.0f), Math::Deg2Rad(150.0f));
				actor.Pitch() = Math::Clampf(actor.Pitch(), Math::Deg2Rad(-60.0f), Math::Deg2Rad(60.0f));
				//vel.z += dir.z * 2.0f;
				
				// vel.x = Math::Clampf(vel.x, minVel.x, maxVel.x);
				// vel.y = Math::Clampf(vel.y, minVel.y, maxVel.y);
				// vel.z = Math::Clampf(vel.z, minVel.z, maxVel.z);
				// vel.x = 0;
				// vel.y = 0;
				//kVec3 newVel = actor.MovementComponent().Velocity() + vel;
				actor.MovementComponent().Velocity() = vel;
				
				int animID = self.AnimTrackComponent().PlayingID();
				if (animID == ANIM_WPN_FIRE_ARTILLERY_LEFT || animID == ANIM_WPN_FIRE_ARTILLERY_RIGHT)
				{
					if(self.AnimTrackComponent().TrackTime() >= FLYING_GUN_TIME_TO_REFIRE)
					{
						self.AnimTrackComponent().Flags() |= ANF_CYCLECOMPLETED;
					}
				}
				
				if ((self.Owner().Buttons() & BC_JUMP) != 0)
				{
					if ((self.GameTicks() & FLYING_GUN_MACHINE_GUN_REFIRE_ITERATION) == 0)
					{
						self.AnimTrackComponent().Blend(ANIM_WPN_FIRE_MACHINE_GUN, 0, 8, 0);
					}
				}
				
				// for (int i = -10; i < 10; i++)
					// self.RenderMeshComponent().SetAttachedMeshVisibility(i, true);
			}
			//------------------------------------------------------------------------------------------------------------------------
		};
	}
}
