// C# 스크립트에서 Unity UI와 터치 이벤트를 사용하기 위해 꼭 필요한 네임스페이스들입니다.
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

// IPointerDownHandler: 터치가 시작될 때 OnPointerDown 함수를 호출합니다.
// IDragHandler: 터치한 채로 드래그할 때 OnDrag 함수를 호출합니다.
// IPointerUpHandler: 터치가 끝났을 때 OnPointerUp 함수를 호출합니다.
public class Joystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
    // --- 내부 변수 --- //
    private Image _background; // 조이스틱의 배경 이미지를 저장할 변수입니다.
    private Image _controller; // 조이스틱의 핸들(컨트롤러) 이미지를 저장할 변수입니다.
    private Vector2 _touchPosition; // 터치된 위치를 저장할 변수입니다.

    
    // --- 외부 변수 --- //
    /// <summary>
    /// 조이스틱 좌우 위치 값 (-1 ~ 1)
    /// </summary>
    public float Horizontal { get; private set; } // 조이스틱의 수평 위치 값 (-1 ~ 1)
    /// <summary>
    /// 조이스틱 상하 위치 값 (-1 ~ 1)
    /// </summary>
    public float Vertical { get; private set; }   // 조이스틱의 수직 위치 값 (-1 ~ 1)

    void Awake()
    {
        _background = GetComponent<Image>();
        _controller = _background.transform.Find("Controller").GetComponent<Image>();
    }

    void Start()
    {
        SetupJoyStick();
        Manager.Input.JoyStick = this;
    }

    // 조이스틱 이미지 화면에 맞게 설정
    private void SetupJoyStick()
    {
        // float size = Screen.height * 0.35f;
        float size = 300f;
        RectTransform bgRect = _background.rectTransform;
        RectTransform crRect = _controller.rectTransform;
        
        bgRect.sizeDelta = new Vector2(size, size);
        crRect.sizeDelta = new Vector2(size * 0.4f, size * 0.4f);
        
        bgRect.anchorMin = new Vector2(0, 0);
        bgRect.anchorMax = new Vector2(0, 0);
        
        bgRect.pivot = new Vector2(0.5f, 0.5f);
        bgRect.anchoredPosition = new Vector2(100f + size / 2, 100f + size / 2);
    }
    

    // [IPointerDownHandler] 터치가 시작될 떄 이 함수 자동 호출.
    public void OnPointerDown(PointerEventData eventData)
    {
        // 드래그 시 자동 호출 되겠지만 터치 시작 시점에도 바로 반응하기 위해서 한 번 호출 함
        OnDrag(eventData);
    }

    //[IDragHandler] 터치하고 드래그시 이 함수 자동 호출.
    public void OnDrag(PointerEventData eventData)
    {
        
        // 화면에서의 터치 좌표를 특정 UI를 기준으로 하는 로컬 좌표로 변환
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
                _background.rectTransform,
                eventData.position,
                eventData.pressEventCamera,
                out _touchPosition))
        {
            // 조이스틱 배경 이미지의 넓이를 기준으로 반지름을 계산합니다.
            float backgroundRadius = _background.rectTransform.sizeDelta.x / 2;

            // 터치 위치의 길이가 반지름보다 크면 (터치가 배경 이미지 밖으로 벗어났다는 소리)
            if (_touchPosition.magnitude > backgroundRadius)
            {
                // 방향은 그대로 유지하며 길이는 반지름 크기로 고정시켜서 컨트롤러가 밖으로 나가지 않게 한다.
                _touchPosition = _touchPosition.normalized * backgroundRadius;
            }

            // 계산된 위치로 _controller 이미지의 위치를 실제로 움직여줍니다.
            _controller.rectTransform.anchoredPosition = _touchPosition;

            // 현재 컨트롤러의 위치를 -1에서 1 사이의 값으로 정규화합니다. (좌하단 = -1, -1 / 우상단 = 1, 1)
            Horizontal = _touchPosition.x / backgroundRadius;
            Vertical = _touchPosition.y / backgroundRadius;
        }
    }

    // 조이스틱 영역에서 터치를 뗐을 때 호출되는 함수
    public void OnPointerUp(PointerEventData eventData)
    {
        // 컨트롤러를 다시 조이스틱의 정중앙으로 되돌립니다.
        _controller.rectTransform.anchoredPosition = Vector2.zero;

        // 플레이어가 계속 움직이는 것을 방지하기 위해, 수평/수직 값을 0으로 초기화합니다.
        Horizontal = 0;
        Vertical = 0;
    }
}