using System.Collections;
using System.Collections.Generic;
using Unity.XR.CoreUtils;
using UnityEngine;
using static MouseLook;

public class CarDrivingRoutine : MonoBehaviour
{
    public AudioSource _stopSound;
    public AudioSource _tireSound;
    public Waypoint _waypoint;

    public float StraightSpeed = 5f; // Movement speed
    public float rotationSpeed = 5f; // Rotation speed
    public float waypointProximityThreshold = 0.5f; // Distance to consider "close enough" to a waypoint
    private bool isTurning = false;
    private float tireTurnAngle = -40;
    private float haltspeed = 1f;
    private float targetSpeed;
    private float targetRotationSpeed;

    [Header("Tires")]
    public List<GameObject> FrontTires;
    public List<GameObject> BackTires;

    private void Start()
    {
        targetSpeed = StraightSpeed;
        targetRotationSpeed = rotationSpeed;
    }

    // Update is called once per frame
    void Update()
    {
        //if (hasPedestrianInFront) return;
        if (_waypoint == null) return; // Just in case.

        // Move towards the waypoint
        Vector3 targetPosition = _waypoint.transform.position;
        float step = StraightSpeed * Time.deltaTime;
        transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);

        // Rotate towards the desired rotation
        float targetRotation = _waypoint.DesiredRotation;
        Quaternion desiredRotation = Quaternion.Euler(0, targetRotation, 0);
        transform.rotation = Quaternion.RotateTowards(transform.rotation, desiredRotation, rotationSpeed * Time.deltaTime);

        rollTires(); // Just an aesthetic improvement.

        if (Quaternion.Angle(transform.rotation, desiredRotation) > 1f) // If the car is turning.
        {
            if (!isTurning)
            {
                setTireRotation(tireTurnAngle);
            }

            isTurning = true;
        }
        if (Quaternion.Angle(transform.rotation, desiredRotation) <= 1f) // Reset the turn value.
        {
            if (isTurning)
            {
                setTireRotation(-tireTurnAngle);
            }

            isTurning = false;
        }

        // Check if close enough to the waypoint
        if (Vector3.Distance(transform.position, targetPosition) <= waypointProximityThreshold &&
            Quaternion.Angle(transform.rotation, desiredRotation) <= 1f)
        {
            // Proceed to the next waypoint
            _waypoint = _waypoint.Next;
        }
    }

    private void rollTires()
    {
        float tireRollModifier = -9 * rotationSpeed; // Multiplies the value so, that the roll looks natural.
        foreach (GameObject tire in FrontTires)
        {
            tire.transform.Rotate(tireRollModifier * Time.deltaTime, 0, 0);
        }
        foreach (GameObject tire in BackTires)
        {
            tire.transform.Rotate(tireRollModifier * Time.deltaTime, 0, 0);
        }
    }

    private void setTireRotation(float rotation)
    {
        foreach (GameObject tire in FrontTires)
        {
            Vector3 currentRotation = tire.transform.eulerAngles;

            currentRotation.y += rotation;

            tire.transform.eulerAngles = currentRotation;
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.GetComponent<XROrigin>() == null) return;
        StartCoroutine(SmoothAdjustSpeed(0, 0, haltspeed)); // Smoothly halt in 1 second
        _tireSound.Stop();
        _stopSound.Play();
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.GetComponent<XROrigin>() == null) return;
        StartCoroutine(SmoothAdjustSpeed(targetSpeed, targetRotationSpeed, haltspeed)); // Smoothly resume speed in 1 second
        _stopSound.Stop();
        _tireSound.Play();
    }

    private IEnumerator SmoothAdjustSpeed(float targetStraightSpeed, float targetRotationSpeed, float duration)
    {
        float initialStraightSpeed = StraightSpeed;
        float initialRotationSpeed = rotationSpeed;
        float elapsedTime = 0f;

        while (elapsedTime < duration)
        {
            elapsedTime += Time.deltaTime;
            float t = elapsedTime / duration;

            // Smooth interpolation (you can use Mathf.Lerp or Mathf.SmoothStep)
            StraightSpeed = Mathf.Lerp(initialStraightSpeed, targetStraightSpeed, t);
            rotationSpeed = Mathf.Lerp(initialRotationSpeed, targetRotationSpeed, t);

            yield return null; // Wait for the next frame
        }

        // Ensure final values are set
        StraightSpeed = targetStraightSpeed;
        rotationSpeed = targetRotationSpeed;
    }
}