using System.Security.Cryptography;
using UnityEngine;
using UnityEngine.EventSystems;

public class MoveController : MonoBehaviour
{
    public float jumpHeight = 2.0f;
    public float gravity = -9.8f;
    private float speed = 6f;
    private float verticalVelocity = 0.0f;
    private bool isGrounded = false;
    private float groundCheckDistance = 0.01f;
    private int groundLayer = ~(1 << 6);
    public PlayerInputComponent playerInput;
    private AnimatorController controller;
    private Vector3 move;
    private Vector3 gravityMove;
    private Vector3 initPos;
    private float offset;
    public Transform camera;

    private float angleX;
    private float angleY;
    public enum PlayerState
    {
        Ground,
        JumpUp,
        JumpDown,
    }

    private CharacterController character;
    public PlayerState state;

    // Start is called before the first frame update
    void Start()
    {
        controller = GetComponent<AnimatorController>();
        character = GetComponent<CharacterController>();
        playerInput=GetComponent<PlayerInputComponent>();
        angleX = Vector3.Angle(Vector3.right, camera.right);
        angleY = Vector3.Angle(Vector3.up, camera.up);
        character.enabled = true;
    }

    // Update is called once per frame
    void Update()
    {
        // ����Ƿ��ڵ�����
        isGrounded = IsGrounded();
        //Debug.Log(isGrounded);
        if (isGrounded)
        {
            // ���¿ո��������Ծ
            if (playerInput.JumpInput)
            {
                state = PlayerState.JumpUp;
                Jump();
                controller.jump = true;
            }

        }
        else
        {
            if (state != PlayerState.JumpUp)
            {
                state = PlayerState.JumpDown;
            }
        }
        if (isGrounded && state == PlayerState.JumpDown)
        {
            state = PlayerState.Ground;
        }
        move = Vector3.zero;
        if (state != PlayerState.Ground)
        {
            // Ӧ������
            ApplyGravity();
        }
        //Debug.Log(playerInput.MoveInput);
        move +=
            new Vector3(playerInput.MoveInput.x, 0, playerInput.MoveInput.y)
            * Time.deltaTime
            * speed;
        // �ƶ�����
        Move();
        UpdateControlRotation();
    }

    void Jump()
    {
        // ������Ծ�ٶ��Դﵽָ������Ծ�߶�
        verticalVelocity = Mathf.Sqrt(-2.0f * gravity * jumpHeight);
    }

    void ApplyGravity()
    {
        // Ӧ��������ģ������Ĵ�ֱ�˶�
        verticalVelocity += gravity * Time.deltaTime;
        // ���ݴ�ֱ�ٶ��ƶ�����
        if (verticalVelocity < 0.1f && verticalVelocity > -0.1f && state == PlayerState.JumpUp)
        {
            state = PlayerState.JumpDown;
        }

        gravityMove = new Vector3(0, verticalVelocity * Time.deltaTime, 0);
    }

    void Move()
    {
        //Debug.Log(playerInput.name + "****" + move);
        //var camRot = new Vector3(0, camera.eulerAngles.y, 0);


        if (playerInput.MoveInput != Vector2.zero)
        {
            Vector3 dir = Vector3.zero;
         
            //Debug.Log(playerInput.MoveInput);
            if (playerInput.MoveInput.x > 0)
            {
                dir = Vector3.ProjectOnPlane(camera.right, Vector3.up);
            }
            if (playerInput.MoveInput.x < 0)
            {
                dir += Vector3.ProjectOnPlane(-camera.right, Vector3.up);
            }
            if (playerInput.MoveInput.y > 0)
            {
                dir += Vector3.ProjectOnPlane(camera.forward, Vector3.up);
            }
            if (playerInput.MoveInput.y < 0)
            {
                dir += Vector3.ProjectOnPlane(-camera.forward, Vector3.up);
            }
            //Debug.Log(dir);
            Vector3 targetDir = Vector3.RotateTowards(
                transform.forward,
                //camera.forward.ProjectOntoPlane(Vector3.up),
                dir,
                10,
                0f
            );
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetDir),Time.deltaTime * 15f);
            //var a = Vector3.Angle(transform.forward.normalized, playerInput.MoveInput.normalized);
            //Quaternion r = Quaternion.Euler(0, a, 0);
            //transform.eulerAngles = r * transform.eulerAngles;
        }
        //var m = move.magnitude * camera.forward + gravityMove;
        //Debug.Log(move + "*******" + "************" + m);
        var angle = AngleSigned(
            Vector3.forward,
            Vector3.ProjectOnPlane(camera.forward, Vector3.up),
        transform.up
        );
        Quaternion rot = Quaternion.Euler(0, angle, 0);
        //Vector3 move2 = camera.transform.TransformDirection(move);
        controller.speed = move.magnitude * 300;
        character.Move(rot * move + gravityMove);
        camera.position= character.transform.position+new Vector3(0,1.148f,0);
    }

    public static float AngleSigned(Vector3 v1, Vector3 v2, Vector3 n)
    {
        return Mathf.Atan2(Vector3.Dot(n, Vector3.Cross(v1, v2)), Vector3.Dot(v1, v2))
            * Mathf.Rad2Deg;
    }

    private Vector3 pointBottom;
    private Vector3 pointTop;
    private float radius = 0.5f;
    private Collider[] colliders;
    private float LerpValue = 0.05f;

    bool IsGrounded()
    {
        // ��������������Ӽ�������Ƿ��ڵ����ϵ��߼�
        // �������߼�⡢��ײ������
        radius = character.radius * 0.9f;
        pointBottom = transform.position + transform.up * radius - transform.up * 0.1f;
        pointTop = transform.position + transform.up * character.height - transform.up * radius;

        colliders = Physics.OverlapCapsule(pointBottom, pointTop, radius, groundLayer);
        Debug.DrawLine(pointBottom, pointTop, Color.red);
        if (colliders.Length != 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    private void UpdateControlRotation()
    {
        if (playerInput.touch0Input != Vector2.zero && playerInput.MoveInput == Vector2.zero && !EventSystem.current.IsPointerOverGameObject())
        {
            //camera.eulerAngles += (new Vector3(playerInput.touch0Input.y, playerInput.touch0Input.x, 0)) * 0.1f;
            angleX += playerInput.touch0Input.x * 10 * Time.fixedDeltaTime;
            angleY -= playerInput.touch0Input.y * 10 * Time.fixedDeltaTime;
            angleY = angleClamp(angleY, -10, 60);//�����ת�Ƕ�����

            //ʹ�ò�ֵƽ����ת
            camera.rotation = Quaternion.Lerp(camera.rotation, Quaternion.Euler(angleY, angleX, 0), Time.fixedDeltaTime * 5);

        }
        if (playerInput.touch1Input != Vector2.zero && !EventSystem.current.IsPointerOverGameObject())
        {
            angleX += playerInput.touch1Input.x * 10 * Time.fixedDeltaTime;
            angleY -= playerInput.touch1Input.y * 10 * Time.fixedDeltaTime;
            angleY = angleClamp(angleY, -10, 60);//�����ת�Ƕ�����

            //ʹ�ò�ֵƽ����ת
            camera.rotation = Quaternion.Lerp(camera.rotation, Quaternion.Euler(angleY, angleX, 0), Time.fixedDeltaTime * 5);
        }

        angleX += playerInput.CameraInput.x * 10 * Time.fixedDeltaTime;
        angleY -= playerInput.CameraInput.y * 10 * Time.fixedDeltaTime;
        angleY = angleClamp(angleY, -10, 60);//�����ת�Ƕ�����

        //ʹ�ò�ֵƽ����ת
        camera.rotation = Quaternion.Lerp(camera.rotation, Quaternion.Euler(angleY, angleX, 0), Time.fixedDeltaTime * 5);
    }

    private static float angleClamp(float angle, float min, float max)
    {//һ�����ƽǶ������Сֵ�ķ���
        if (angle < -360)
            angle += 360;
        if (angle > 360)
            angle -= 360;
        return Mathf.Clamp(angle, min, max);
    }

}