using UnityEngine;

public class MagnetController : MonoBehaviour
{
    [SerializeField] private GameObject player;
    [SerializeField] private float distanceFromPlayer = 1.2f;
    [SerializeField] private float distanceAttract = 5f;
    [SerializeField] private float attractForce = 10f;
    [SerializeField] private float impulseForce = 20f;
    [SerializeField] private float distanceToBlock = 0.5f;
    [SerializeField] private LayerMask metalLayer;
    [SerializeField] private GameObject attractPoint;

    private bool isAttracting = false;
    private Rigidbody2D rb;
    private Rigidbody2D attractedObject;
    private TargetJoint2D joint;
    private FixedJoint2D grabJoint;

    void Start()    
    {
        rb = GetComponent<Rigidbody2D>();
        joint = GetComponent<TargetJoint2D>();

        joint.anchor = Vector2.zero;
    }
    
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            Attract();
        }
        if (Input.GetMouseButtonUp(0))
        {
            Launch();
        }
    }
    
    void FixedUpdate()
    {
        Rotate();
    }

    void Rotate()
    {
        Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector2 playerPos = player.transform.position;
        Vector2 direction = (mousePos - (Vector2)playerPos).normalized;

        float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        rb.MoveRotation(angle);
        
        Vector2 targetPosition = (Vector2)playerPos + (direction * distanceFromPlayer);
        joint.target = targetPosition;

        float currentDistance = Vector2.Distance(transform.position, playerPos);
        float maxDistance = distanceFromPlayer + 1f;

        if (currentDistance >= maxDistance)
        {
            rb.position = targetPosition;
        }
    }    

    void Attract()
    {
        if (attractedObject == null)
        {
            Vector2 boxSize = GetComponent<BoxCollider2D>().size;
            RaycastHit2D raycastHit = Physics2D.BoxCast(transform.position, boxSize, transform.eulerAngles.z, transform.right, distanceAttract, metalLayer);

            if (raycastHit.collider != null)
            {
                attractedObject = raycastHit.collider.GetComponent<Rigidbody2D>();
            }
        }

        if (attractedObject != null)
        {
            Vector2 direction = (transform.position - attractedObject.transform.position).normalized;
            float distance = Vector2.Distance(transform.position, attractedObject.transform.position);

            if (distance < distanceToBlock)
            {
                if (grabJoint == null)
                {
                    grabJoint = gameObject.AddComponent<FixedJoint2D>();
                    grabJoint.connectedBody = attractedObject;
                    grabJoint.breakForce = Mathf.Infinity;

                    grabJoint.frequency = 3f;
                    grabJoint.dampingRatio = 0.5f;

                    Physics2D.IgnoreCollision(attractedObject.GetComponent<Collider2D>(), player.GetComponent<Collider2D>(), true);
                }
            }
            else
            {
                attractedObject.AddForce(direction * attractForce);
            }
        }
    }

    void Launch()
    {
        if (attractedObject != null)
        {
            if (grabJoint != null)
            {
                Destroy(grabJoint);
            }
            
            Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            Vector2 direction = (mousePos - (Vector2)transform.position).normalized;
            attractedObject.AddForce(direction * impulseForce, ForceMode2D.Impulse);

            Physics2D.IgnoreCollision(attractedObject.GetComponent<Collider2D>(), player.GetComponent<Collider2D>(), false);
            attractedObject = null;
        }
    }
}