using UnityEngine;

public class PlayerHeadController : MonoBehaviour
{
    [Header("Head")]
    public Transform Head;
    public Transform CameraTransform;
    public Transform BodyTransform;
    public float ThrowForce;
    public float PickupDistance;
    public bool isHoldingHead;

    [Header("Grabbable")]
    public Transform HandTransform; // in the future hand maybe grab items but for now its an empty object
    public float ItemThrowForce = 10f;
    public float ItemPickupDistance = 5f;

    private bool isHoldingItem;
    private Rigidbody m_itemRigidbody;
    private Collider m_itemCollider;
    private Transform m_currentItem;

    private Rigidbody m_headRigidbody;
    private Vector3 m_headInitialLocalPos;
    private Quaternion m_headInitialLocalRot;

    private Animator animator;
    private PlayerInputController input;

    private void Awake()
    {
        animator = GetComponent<Animator>();
        input = GetComponent<PlayerInputController>();
    }

    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;

        Vector3 offset = new Vector3(0f, -0.5f, 0.5f);
        m_headInitialLocalPos = BodyTransform.localPosition + offset;
        m_headInitialLocalRot = BodyTransform.localRotation;
        m_headRigidbody = Head.GetComponent<Rigidbody>();

        Head.SetParent(null);
    }

    void Update()
    {
        if (input.HeadInteractionPressed)
            InteractHead();

        if (input.ThrowPressed && isHoldingHead)
            ThrowHead();

        if (input.InteractPressed)
        {
            if (!isHoldingItem)
                TryPickupItem();
            else
                DropItem();
        }
        if (input.ThrowPressed && isHoldingItem)
            ThrowItem();
    }

    private void InteractHead()
    {
        if (!isHoldingHead)
            TryPickupHead();
        else
            DropHead();
    }

    private void TryPickupHead()
    {
        if (isHoldingHead || isHoldingItem) 
            return;
        if (Vector3.Distance(transform.position, Head.position) <= PickupDistance)
            PickupHead();
    }

    private void PickupHead()
    {
        isHoldingHead = true;

        if (m_headRigidbody != null)
            Destroy(m_headRigidbody);

        Head.SetParent(transform);
        Head.localPosition = m_headInitialLocalPos;
        Head.localRotation = m_headInitialLocalRot;
    }
    private void DropHead()
    {
        animator.SetTrigger("Throw");
        isHoldingHead = false;

        Head.SetParent(null);

        m_headRigidbody = Head.gameObject.AddComponent<Rigidbody>();
        m_headRigidbody.mass = 1f;
        m_headRigidbody.constraints =
            RigidbodyConstraints.FreezeRotationX |
            RigidbodyConstraints.FreezeRotationZ |
            RigidbodyConstraints.FreezeRotationY;
    }
    private void ThrowHead()
    {
        DropHead();
        m_headRigidbody.AddForce(CameraTransform.forward * ThrowForce, ForceMode.Impulse);
    }
    private void TryPickupItem()
    {
        if (isHoldingHead || isHoldingItem)
            return;
        int grabbableLayer = LayerMask.GetMask("Grabbable");
        Collider[] hits = Physics.OverlapSphere(transform.position, ItemPickupDistance, grabbableLayer);

        foreach (Collider hit in hits)
        {
            m_currentItem = hit.transform;
            m_itemRigidbody = hit.GetComponent<Rigidbody>();
            m_itemCollider = hit.GetComponent<Collider>();
            PickupItem();
            return;
        }
    }

    private void PickupItem()
    {
        isHoldingItem = true;
        m_itemRigidbody.isKinematic = true;
        m_itemCollider.enabled = false;

        m_currentItem.SetParent(HandTransform);
        m_currentItem.localPosition = Vector3.zero;
        m_currentItem.localRotation = Quaternion.identity;
    }

    private void DropItem()
    {
        isHoldingItem = false;
        m_currentItem.SetParent(null);
        m_itemRigidbody.isKinematic = false;
        m_itemCollider.enabled = true;
        m_currentItem = null;
    }

    private void ThrowItem()
    {
        DropItem();
        m_itemRigidbody.AddForce(BodyTransform.forward * ItemThrowForce, ForceMode.Impulse);
    }
}