using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;

public class InputManager: IManager
{
    private InputActions _action;
    private Dictionary<string, Action> _registeredActions = new Dictionary<string, Action>();
    
    public Joystick JoyStick { get; set; }
    // 화면 터치를 어떻게 받아올건지에 대한 액션
    public Action<Define.InputEvent> InputAction = null;
    // 화면의 터치하는 실시간 좌표를 사용하는 기능을 위한 액션
    public Action<Vector2> PointAction = null;
    // 조이스틱의 이동을 담당하는 액션
    public Action<Vector2> MoveAction = null;
    
    bool _pressed = false;
    float _pressedTime = 0.0f;
    
    public void Init()
    {
        _action = new InputActions();
        _action.UI.Enable();
    }

    public void OnUpdate()
    {
        JoystickInput();
        AnyInput();
    }
    void JoystickInput()
    {
        if (JoyStick == null)
            return;

        Vector2 dir = new Vector2(JoyStick.Horizontal, JoyStick.Vertical);
        MoveAction?.Invoke(dir);
    }


    void AnyInput()
    {
        PointAction?.Invoke(_action.UI.Point.ReadValue<Vector2>());
        
        if (InputAction != null)
        {
            // UI 위에 마우스(손가락)가 올라가 있는지 체크
            if (EventSystem.current.IsPointerOverGameObject())
            {
                if (_pressed)
                {
                    InputAction.Invoke(Time.time - _pressedTime < 0.2f
                        ? Define.InputEvent.Click
                        : Define.InputEvent.Up);
                }

                _pressed = false;
                _pressedTime = 0.0f;
                return;
            }

            if (_action.UI.Touch.IsPressed())
            {
                // Touch를 누르고 있는 상태 
                if (!_pressed)
                {
                    InputAction.Invoke(Define.InputEvent.Down);
                    _pressedTime = Time.time;
                }

                InputAction.Invoke(Define.InputEvent.Press);
                _pressed = true;
            }
            else
            {
                if (_pressed)
                {
                    if (Time.time - _pressedTime < 0.2f)
                        InputAction.Invoke(Define.InputEvent.Click);
                    else
                        InputAction.Invoke(Define.InputEvent.Up);

                    _pressed = false;
                    _pressedTime = 0.0f;
                }
            }
        }
    }

    public void RegisterAction(string name, Action action)
    {
        if (!_registeredActions.ContainsKey(name)) _registeredActions[name] = null;
        UnregisterAction(name, action);
        _registeredActions[name] += action;
    }
    
    public void UnregisterAction(string name, Action action)
    {
        if (_registeredActions.ContainsKey(name)) _registeredActions[name] -= action;
    }

    //MARK: ACTION INVOKE
    public void OnClicked(string name)
    {
        if(_registeredActions.TryGetValue(name, out Action action)) action?.Invoke();
    }
    
    //MARK: CLEAR
    public void Clear()
    {
        _action.Dispose();
        InputAction = null;
        PointAction = null;
        
        MoveAction = null;
        JoyStick = null;
        
        _registeredActions.Clear();
    }
}