using UnityEngine;
using UnityEngine.InputSystem;

namespace StudyCase3
{
    public enum PickMode
    {
        RayCast,
        Mouse
    }
    public class ThirdCharacterController : MonoBehaviour
    {
        [Header("MoveSettings")]
        CharacterController characterController;
        InputActionAsset inputAction;
        Animator animator;
        Transform forward;
        Transform model;
        Cinemachine.CinemachineVirtualCamera vCam;
        public float moveSpeed = 5f;
        public float jumpSpeed = 2f;
        public float turnSpeed = 10f;
        public float gravity = 10f;
        Vector3 moveDir;
        Vector2 moveInput;
        [Header("PickSettings")]
        public PickMode pickMode = PickMode.RayCast;
        public CursorLockMode cursorLock;
        public bool useDrawRay = true;
        public float maxDistance = 5f;
        public LayerMask layerMask;
        public float itemsRotateSpeed = 120f;
        public Transform itemRoot;
        Item selectItem;
        LineRenderer lineRenderer;
        private void Awake()
        {
            Cursor.lockState = cursorLock;
            characterController = GetComponent<CharacterController>();
            forward = transform.Find("Forward");
            model = transform.Find("Model");
            animator = model.GetComponentInChildren<Animator>();
            vCam = transform.Find("Virtual Camera").GetComponent<Cinemachine.CinemachineVirtualCamera>();
            inputAction = Resources.Load<InputActionAsset>("PlayerInputActions");
            inputAction.FindAction("Move").started += OnMove;
            inputAction.FindAction("Move").performed += OnMove;
            inputAction.FindAction("Move").canceled += OnMove;
            inputAction.FindAction("Jump").performed += OnJump;
            inputAction.FindAction("Pick").performed += OnPickUp;
            inputAction.Enable();
            itemRoot = transform.Find("ItemRoot");
            if (lineRenderer == null)
            {
                lineRenderer = gameObject.AddComponent<LineRenderer>();
                lineRenderer.material = new Material(Shader.Find("Universal Render Pipeline/2D/Sprite-Unlit-Default"));
                lineRenderer.useWorldSpace = true;
            }
        }
        private void Update()
        {
            Move();
            CheckRayHit();
            ItemsRotate();
        }
        public void OnMove(InputAction.CallbackContext context)
        {
            if (characterController.isGrounded)
                moveInput = context.ReadValue<Vector2>();
            else moveInput = Vector2.zero;
        }
        public void OnJump(InputAction.CallbackContext context)
        {
            if (context.performed && characterController.isGrounded)
            {
                moveDir.y = jumpSpeed;
            }
        }
        void Move()
        {
            moveDir = new Vector3(moveInput.x, moveDir.y, moveInput.y);
            forward.eulerAngles = new Vector3(0, vCam.transform.eulerAngles.y, 0);
            moveDir = forward.TransformDirection(moveDir);
            if (moveInput != Vector2.zero)
            {
                animator?.SetBool("Move", true);
                Quaternion target = Quaternion.LookRotation(new Vector3(moveDir.x, 0, moveDir.z));
                model.rotation = Quaternion.Slerp(model.rotation, target, turnSpeed * Time.deltaTime);
            }
            else animator?.SetBool("Move", false);
            if (!characterController.isGrounded)
                moveDir.y -= gravity * Time.deltaTime;
            characterController.Move(moveDir * moveSpeed * Time.deltaTime);
        }
        #region PickUp
        public void OnPickUp(InputAction.CallbackContext context)
        {
            if (pickMode != PickMode.RayCast) return;
            if (selectItem != null)
                selectItem.PickUp(itemRoot);
            selectItem = null;
        }
        void CheckRayHit()
        {
            lineRenderer.enabled = useDrawRay;
            if (pickMode != PickMode.RayCast) 
            {
                useDrawRay = false;
                return;
            }
            Ray ray = new Ray(model.position, model.forward);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, maxDistance, layerMask))
            {
                DrawRay(model.position, hit.point, new Color(0, 1, 1));
                Item curItem = hit.transform.GetComponent<Item>();
                if (curItem != null && curItem != selectItem)
                {
                    if (selectItem != null)
                        selectItem.UnSelect();
                    selectItem = curItem;
                    selectItem.Select();
                }
            }
            else
            {
                DrawRay(model.position, model.position+ model.forward* maxDistance, new Color(1, 1, 1));
                if (selectItem != null)
                    selectItem.UnSelect();
                selectItem = null;
            }
        }
        void DrawRay(Vector3 startPos, Vector3 endPos, Color color)
        {
            lineRenderer.startColor = lineRenderer.endColor = color;
            lineRenderer.startWidth = lineRenderer.endWidth = 0.1f;
            lineRenderer.positionCount = 2;
            lineRenderer.SetPosition(0, startPos);
            lineRenderer.SetPosition(1, endPos);
            lineRenderer.enabled = true;
        }
        void ItemsRotate()
        {
            itemRoot.Rotate(0,itemsRotateSpeed*Time.deltaTime, 0);
        }
        public void SetItems()
        {
            float radius = 1.5f;
            float angleStep = 360 / itemRoot.childCount;
            for (int i = 0; i < itemRoot.childCount; i++)
            {
                Transform item = itemRoot.GetChild(i);
                float angle = angleStep * i;
                Quaternion rot = Quaternion.Euler(0, angle, 0);
                item.localPosition = rot * itemRoot.forward * radius;
                item.localScale = Vector3.one * 0.1f;
            }
        }
        #endregion
    }
}