using System;
using Obvious.Soap;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Conjure.Input
{
    public class CharacterMovements : SerializedMonoBehaviour
    {
        [Required]
        [SerializeField] private Vector3Variable playerMoveDirection;
        [Required]
        [SerializeField] private FloatVariable movementSpeed;
        [SerializeField, Required] private Animator animator;
        
        [SerializeField, ReadOnly, FoldoutGroup("Debug")] private Vector3 direction = Vector3.zero;
        [SerializeField, ReadOnly, FoldoutGroup("Debug")] private Rigidbody RB;
        private static readonly int Moving = Animator.StringToHash("Moving");

        // Start is called before the first frame update
        void Start()
        {
            //CC = GetComponent<CharacterController>();
            if (!TryGetComponent(out RB))
            {
                throw new NullReferenceException($"A Rigidbody should be available on this GameObject: {transform.name}");
            }

            if (animator == null)
            {
                throw new NullReferenceException($"An Animator should be available on this GameObject: {transform.name}");
            }
            
            playerMoveDirection.OnValueChanged += UpdateDirection;
        }

        private void FixedUpdate()
        {
            RB.velocity = direction * movementSpeed.Value;
        }

        private void UpdateDirection(Vector3 newDirection)
        {
            float movementMagnitude = newDirection.magnitude;
            animator.SetBool(Moving, movementMagnitude > 0);
            
            if (movementMagnitude != 0)
            {
                AssignNewRotation(newDirection);
            }
            
            direction = newDirection;
        }

        private void AssignNewRotation(Vector3 newDirection)
        {
            Vector3 rotation = new Vector3(0, Vector3.Angle(newDirection, Vector3.right), 0);
            if (newDirection.z > 0)
            {
                rotation.y *= -1;
            }
            transform.localRotation = Quaternion.Euler(rotation);
        }

        private void OnDestroy()
        {
            playerMoveDirection.OnValueChanged -= UpdateDirection;
        }
    }
}
