using UnityEngine;
using static AffectingForcesManager;

public class HitFeedbackTestObjectBehavior : MonoBehaviour
{
	// Private variables
	public AffectingForcesManager forceManager;
	[SerializeField] private float normalMaxVelocity = 10;
	[SerializeField] private float absolutMaxVelocity = 20;
	[SerializeField] private bool useAntiDrift = false;
	[SerializeField] private float antiDriftAmount = 20;
	[SerializeField] private float minAntiDriftFactor = 0.2f;
	[SerializeField] private float normalDrag = 0.1f;
	[SerializeField] private float maximumDrag = 0.3f;
	[SerializeField] private float torqueDrag = 0.2f;
	[SerializeField] private float tackleStunTime = 0.6f;
	// The time in Seconds the player is allowed to boost for
	private Rigidbody body;
	private Vector3 currentGravity = new Vector3();
	// Current Zone the player occupies
	private Zone zone = Zone.NimbleZone;
	private int instanceID;
	private bool isTackled;
	private float tackledTime;
	// Start is called before the first frame update
	void Start()
	{
		body = GetComponent<Rigidbody>();
		instanceID = gameObject.GetInstanceID();
	}

	// Update is called once per frame
	void FixedUpdate()

	{
		zone = forceManager.GetZoneOfInstance(instanceID);
		//BoostStateUpdate(Time.deltaTime);
		// Rotate the vehicle with the current steer velocity
		// Calculate the magnitude of the acceleration with the current thrust
		UpdateMovement();
		UpdateTackleResponse();
	}

	void UpdateMovement()
	{

		// Get and apply the current Gravity
		currentGravity = forceManager.GetGravityForInstance(instanceID)(transform.position);
		body.AddForce(currentGravity, ForceMode.Acceleration);


		Vector3 currentVelocity = body.velocity;

		if (useAntiDrift && !isTackled)
		{
			Vector3 driftDampeningAcceleration = DriftDampeningAcceleration(currentVelocity, zone);
			// Add anti drift acceleration
			body.AddForce(driftDampeningAcceleration, ForceMode.Acceleration);
		}

		if (currentVelocity.magnitude >= absolutMaxVelocity && !isTackled)
		{
			body.velocity = body.velocity.normalized * absolutMaxVelocity;
		}

		// Add drag
		if (!isTackled)
		{
			Vector3 dragDecceleration = DragDecceleration(currentVelocity, zone);
			body.AddForce(dragDecceleration, ForceMode.Acceleration);
		}

		// Default torque drag
		body.AddTorque(body.angularVelocity * -torqueDrag, ForceMode.Acceleration);

		Debug.DrawRay(transform.position, currentVelocity * 0.5f, Color.black);
	}

	Vector3 DriftDampeningAcceleration(Vector3 currentVelocity, Zone zone)
	{
		Vector3 antiDriftVelocity = new Vector3();
		float antiDriftFactor = 1f;
		// Cancel out inertia/drifting
		if (zone == Zone.NimbleZone)
		{
			Vector3 rotation = transform.rotation.eulerAngles;
			Vector3 driftVelocity = currentVelocity - Vector3.Project(currentVelocity, rotation);
			antiDriftVelocity = Vector3.Reflect(-driftVelocity, transform.up) - driftVelocity;
			antiDriftFactor = Mathf.InverseLerp(absolutMaxVelocity, normalMaxVelocity,
				currentVelocity.magnitude);
			antiDriftFactor = Mathf.Max(antiDriftFactor, minAntiDriftFactor);
			Debug.DrawRay(transform.position, driftVelocity.normalized * 5, Color.red);
		}
		Debug.DrawRay(transform.position, antiDriftVelocity.normalized * 5, Color.green);
		return antiDriftVelocity * antiDriftAmount * antiDriftFactor;
	}

	Vector3 DragDecceleration(Vector3 currentVelocity, Zone zone)
	{
		Vector3 drag = new Vector3();
		float minDragFactor = Mathf.InverseLerp(absolutMaxVelocity, normalMaxVelocity,
			currentVelocity.magnitude);
		float normalDragFactor = Mathf.InverseLerp(normalMaxVelocity, 0, currentVelocity.magnitude);
		if (zone == Zone.NimbleZone)
		{
			drag -= currentVelocity.normalized * normalDrag;
		}
		if (currentVelocity.magnitude >= normalMaxVelocity && zone == Zone.NimbleZone)
		{
			drag -= currentVelocity.normalized * maximumDrag;
		}
		return drag;
	}

	void UpdateTackleResponse(bool gotTackled = false)
	{
		if (gotTackled)
		{
			isTackled = true;
			tackledTime = tackleStunTime;
			return;
		}
		tackledTime -= Time.deltaTime;
		if (tackledTime <= 0)
		{
			isTackled = false;
			tackledTime = 0;
		}
	}

	void OnTriggerEnter(Collider collider)
	{
		if (collider.tag == "Zone")
		{
			return;
		}
		Vector3 colliderVelocity = collider.attachedRigidbody.velocity;
		Vector3 tackleDirection = body.transform.position - collider.transform.position;
		float colliderMass = collider.attachedRigidbody.mass;
		body.AddForce(colliderVelocity.magnitude * tackleDirection * (colliderMass / body.mass),
			ForceMode.Acceleration);
		UpdateTackleResponse(true);
	}


}
