namespace BP
{
	const float DASH_LENGTH = 0.4f;
	const float DASH_INPUT_TIME = 0.25f;
	const float DASH_COOLDOWN = 0.5f;
	
	class Dash
	{
		float inputTime; //double tap dash time (time between inputs)
		float cooldown; //time until can dash again
		float timeLength; //How long the dash effect last has left
		float forwardSpeed = 8.0f;
		float jumpSpeed = 5.0f;
		float forwardDirectionX;
		float forwardDirectionY;
		float lastYawOffset;
		//------------------------------------------------------------------------------------------------------------------------
		Dash()
		{
			
		}
		//------------------------------------------------------------------------------------------------------------------------
		#ifdef BP_DEBUG
		kStr ToString()
		{
			return "inputTime: " + inputTime + " cooldown: " + cooldown + " timeLength: " + timeLength +
					" forwardSpeed: " + forwardSpeed + " jumpSpeed: " + jumpSpeed + " forwardDirectionX: " + forwardDirectionX +
					" forwardDirectionY: " + forwardDirectionY + " lastYawOffset: " + lastYawOffset;
		}
		#endif
		//------------------------------------------------------------------------------------------------------------------------
		void Serialize(kDict& in dict, const kStr& in key)
		{
			SERIALIZE_FLOAT(inputTime);
			SERIALIZE_FLOAT(cooldown);
			SERIALIZE_FLOAT(timeLength);
			SERIALIZE_FLOAT(forwardSpeed);
			SERIALIZE_FLOAT(jumpSpeed);
			SERIALIZE_FLOAT(forwardDirectionX);
			SERIALIZE_FLOAT(forwardDirectionY);
		}
		//------------------------------------------------------------------------------------------------------------------------
		void Deserialize(kDict& in dict, const kStr& in key)
		{
			DESERIALIZE_FLOAT(inputTime);
			DESERIALIZE_FLOAT(cooldown);
			DESERIALIZE_FLOAT(timeLength);
			DESERIALIZE_FLOAT(forwardSpeed);
			DESERIALIZE_FLOAT(jumpSpeed);
			DESERIALIZE_FLOAT(forwardDirectionX);
			DESERIALIZE_FLOAT(forwardDirectionY);
		}
		//------------------------------------------------------------------------------------------------------------------------
		// if is able to dash then dashs in the forward direction + yawOffset of the actor. Returns true if did dash.
		//------------------------------------------------------------------------------------------------------------------------
		bool TryInput(kActor@ actor, float yawOffset)
		{
			bool didDash = false;
			//last input was in the same direction as current input and isn't on cooldown and pressed within a certain time
			if (Math::Approximately(lastYawOffset, yawOffset) && cooldown <= 0.0f && inputTime > 0.0f && inputTime < DASH_INPUT_TIME)
			{
				inputTime = 0.0f;
				cooldown = DASH_COOLDOWN;
				timeLength = DASH_LENGTH;
				actor.MovementComponent().Velocity().z += jumpSpeed;
				forwardDirectionX = Math::Sin(actor.Yaw() + yawOffset);
				forwardDirectionY = Math::Cos(actor.Yaw() + yawOffset);
				didDash = true;
			}
			else
			{
				inputTime = DASH_INPUT_TIME;
			}
			
			lastYawOffset = yawOffset;
			return didDash;
		}
		//------------------------------------------------------------------------------------------------------------------------
		void OnTick(kActor@ actor)
		{
			inputTime -= GAME_DELTA_TIME;
			cooldown -= GAME_DELTA_TIME;
			timeLength -= GAME_DELTA_TIME;
			if (timeLength > 0.0f)
			{
				float speed = Math::Sin((timeLength / DASH_LENGTH) * Math::pi) * this.forwardSpeed;
				actor.MovementComponent().Velocity() += kVec3(forwardDirectionX * speed, forwardDirectionY * speed, 0.0f);
			}
		}
		//------------------------------------------------------------------------------------------------------------------------
	};
}
