using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour, IGrabber
{
    public Transform TransformComponent { get; private set; }
    public Rigidbody2D RigidbodyComponent { get; private set; }

    public GameObject StickRotationSprite { get { return m_StickRotationSprite; } }
    public GameObject ButtonMashSprite { get { return m_ButtonMashSprite; } }

    public int Index { get; set; }

    [SerializeField] private float m_MovementSpeed;
    [SerializeField] private Vector2 m_InteractionBoxSize;
    [SerializeField] private LayerMask m_InteractionMask;

    [SerializeField] private GameObject m_StickRotationSprite;
    [SerializeField] private GameObject m_ButtonMashSprite;

    private Vector2 m_Velocity;

    private Vector2 m_FacingDirection;

    private AnimationComponent m_AnimationComponent;
    private SoundComponent m_SoundComponent;

    private IGrabbable m_GrabbedObj;

    private bool m_IsAsleep = false;

    private void Awake()
    {
        TransformComponent = transform;
        RigidbodyComponent = GetComponent<Rigidbody2D>();
        m_AnimationComponent = GetComponent<AnimationComponent>();
        m_SoundComponent = GetComponent<SoundComponent>();
    }

    private void FixedUpdate()
    {
        RigidbodyComponent.velocity = m_Velocity;

        float speed = m_Velocity.magnitude;

        m_AnimationComponent.SetSpeed(speed);
        m_SoundComponent.SetSpeed(speed);

        if (m_Velocity != Vector2.zero)
        {
            m_FacingDirection = Mathf.Abs(m_Velocity.x) >= Mathf.Abs(m_Velocity.y) ? Vector2.right * Mathf.Sign(m_Velocity.x) : Vector2.up * Mathf.Sign(m_Velocity.y);
            m_AnimationComponent.SetFacing(m_FacingDirection);
        }
    }

    private void Update()
    {
        Debug.DrawRay(RigidbodyComponent.position, m_FacingDirection, Color.green);
    }

    public void SetVelocity(Vector2 dir)
    {
        m_Velocity = dir.normalized * Mathf.Min(dir.magnitude, 1) * m_MovementSpeed;
    }

    public void Interact()
    {
        if (m_IsAsleep)
            return;

        Collider2D coll = Physics2D.OverlapBox(RigidbodyComponent.position + m_FacingDirection * m_InteractionBoxSize.x / 2, m_InteractionBoxSize, Vector2.SignedAngle(Vector2.right, m_FacingDirection), m_InteractionMask);
        
        if (coll)
        {
            IInteractable interactable = coll.GetComponent<IInteractable>();
            interactable?.Interact(this);
        }
    }

    public void Grab()
    {
        if (m_IsAsleep)
            return;

        if (m_GrabbedObj == null)
        {
            Collider2D coll = Physics2D.OverlapBox(RigidbodyComponent.position + m_FacingDirection * m_InteractionBoxSize.x / 2, m_InteractionBoxSize, Vector2.SignedAngle(Vector2.right, m_FacingDirection), m_InteractionMask);

            if (coll)
            {
                IGrabbable grabbable = coll.GetComponent<IGrabbable>();

                if (grabbable != null) Grab(grabbable);
            }
        }
        else
        {
            m_GrabbedObj.OnLeave(this);
            m_GrabbedObj = null;
            m_SoundComponent.StopDragging();
        }
    }

    public void Grab(IGrabbable grabbable)
    {
        if (grabbable.CanBeGrabbed)
        {
            m_GrabbedObj = grabbable;
            m_GrabbedObj.OnGrab(this);
            m_SoundComponent.StartDragging();
        }
    }

    public void Sleep()
    {
        RigidbodyComponent.Sleep();
        m_IsAsleep = true;
        m_AnimationComponent.SetSpeed(0.0f);
        RigidbodyComponent.isKinematic = true;
        enabled = false;
    }

    public void WakeUp()
    {
        ButtonMashSprite.SetActive(false);
        StickRotationSprite.SetActive(false);
        m_IsAsleep = false;
        RigidbodyComponent.WakeUp();
        RigidbodyComponent.isKinematic = false;
        enabled = true;
    }
}
