using UnityEngine;
using UnityEngine.SceneManagement;

namespace FastArena
{
    public class PlayerController : MonoBehaviour
    {
        [HideInInspector] public Player Player;
        public PlayerSettings Settings;
        public Camera PlayerCamera;

        private float maxVerticalSpeed;
        private float rotationX;
        [HideInInspector] public float mouseSens;
        private float lastJumpTime;
        
        private void Awake()
        {
            Player = GetComponent<Player>();
            Settings = new PlayerSettings();
            maxVerticalSpeed = Mathf.Sqrt(-2 * Physics.gravity.y * Player.JumpHeight);
            Cursor.lockState = CursorLockMode.Locked;
            PlayerCamera.fieldOfView = Settings.FieldOfView;
            mouseSens = Settings.MouseSensivity;
            QualitySettings.vSyncCount = 0;
            Application.targetFrameRate = Settings.TargetFPS;
        }

        public bool IsGrounded()
        {
            float sphere_radius = Player.CapsuleCollider.radius * 0.98f;
            Vector3 sphere_origin = Player.transform.position;
            sphere_origin.y += sphere_radius * 1.1f;
            float sphere_travel_distance = sphere_radius * 0.2f;
            bool is_grounded = Physics.SphereCast(sphere_origin, sphere_radius,
                Vector3.down, out var hit, sphere_travel_distance);
            // Debug.Log($"is_grounded: {is_grounded} o={sphere_origin} r={sphere_radius} ");
            return is_grounded;
        }
        
        private void FixedUpdate()
        {
            // camera rotation
            float mouseSensX = mouseSens * Screen.width / Screen.height;
            float mouseSensY = mouseSens * Screen.height / Screen.width;
            rotationX -= Input.GetAxis("Mouse Y") * mouseSensY;
            rotationX = Mathf.Clamp(rotationX, -90, 90);
            Player.CameraPoint.transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
            // character rotation
            float rotationY = Input.GetAxis("Mouse X") * mouseSensX;
            transform.Rotate(new Vector3(0, rotationY, 0));
            
            // mouse buttons
            if (Player.HasTool)
            {
                if (Input.GetKey(KeyCode.Mouse0))
                    Player.CurrentTool.Use0();
                if (Input.GetKey(KeyCode.Mouse1))
                    Player.CurrentTool.Use1();
                if (Input.GetKey(KeyCode.Mouse2))
                    Player.CurrentTool.Use2();
            }

            // numbers
            else if (Input.GetKey(KeyCode.Alpha1))
                Player.SelectTool(0);
            else if (Input.GetKey(KeyCode.Alpha2))
                Player.SelectTool(1);
            else if (Input.GetKey(KeyCode.Alpha3))
                Player.SelectTool(2);
            else if (Input.GetKey(KeyCode.Alpha4))
                Player.SelectTool(3);
            else if (Input.GetKey(KeyCode.Alpha5))
                Player.SelectTool(4);
            else if (Input.GetKey(KeyCode.Alpha6))
                Player.SelectTool(5);
            else if (Input.GetKey(KeyCode.Alpha7))
                Player.SelectTool(6);
            else if (Input.GetKey(KeyCode.Alpha8))
                Player.SelectTool(7);
            else if (Input.GetKey(KeyCode.Alpha9))
                Player.SelectTool(8);
            if (Input.GetKey(KeyCode.Alpha0))
                Player.SelectTool(9);

            // movement control
            var currentVelocity = Player.Rigid.velocity;
            var newVelocity = new Vector3
            {   x = 0,
                y = currentVelocity.y,
                z = 0
            };

            // x,z axes
            if (Input.GetKey(Settings.KeyBindings.MoveForward))
                newVelocity += transform.forward * Player.MovementSpeed;
            if (Input.GetKey(Settings.KeyBindings.MoveBackward))
                newVelocity -= transform.forward * Player.MovementSpeed;
            if (Input.GetKey(Settings.KeyBindings.MoveLeft))
                newVelocity -= transform.right * Player.StrafeSpeed;
            if (Input.GetKey(Settings.KeyBindings.MoveRigth))
                newVelocity += transform.right * Player.StrafeSpeed;
            
            // y axis
            if (Input.GetKey(Settings.KeyBindings.Jump))
            {
                if (IsGrounded())
                {
                    float timeNow = Time.time;
                    if (timeNow - lastJumpTime > Player.JumpCooldown)
                    {
                        // jump
                        newVelocity.y += maxVerticalSpeed;
                        lastJumpTime = timeNow;
                    }
                }
            }

            if(currentVelocity != newVelocity)
            {
                Player.Rigid.velocity = newVelocity;
                // Debug.Log($"current: {currentVelocity} new: {newVelocity} vel: {Player.Rigid.velocity}");
            }
        }

        private void OnDestroy()
        {
            SceneManager.LoadScene("MainMenuScene", LoadSceneMode.Additive);
            Cursor.lockState = CursorLockMode.None;
        }
    }
}