using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviour {
    public float MovementSpeed;
    public float JumpVelocity;
    [Tooltip("How long after falling off a ledge can the player still jump?")]
    public float JumpGracePeriod;
    [Tooltip("Lower values make the movement feel floatier.")]
    public float Antislipperiness = 1;
    [Tooltip("Lower values make the movement feel floatier in air.")]
    public float AntislipperinessInAir = 1;

    [Header("Runtime values")]
    public bool Grounded;

    private CharacterController Character;

    private Vector3 GroundVelocity = new Vector3();
    private float FallingVelocity;
    private float LastGroundedTime;

    private void Awake() {
        Character = GetComponent<CharacterController>();
    }

    private void Start() {
        LastGroundedTime = -JumpGracePeriod;
        Grounded = false;
    }

    private void Update() {
        // Groundedness stuff and gravity
        if (Character.isGrounded) {
            FallingVelocity = Mathf.Max(0, FallingVelocity);
            LastGroundedTime = Time.time;
        } else {
            FallingVelocity += Physics.gravity.y * Time.deltaTime;
        }
        Grounded = Time.time - LastGroundedTime <= JumpGracePeriod && FallingVelocity <= 0;

        // Jumping
        if (Input.GetButton("Jump") && Grounded) {
            FallingVelocity = JumpVelocity;
            Grounded = false;
        }

        float SlippyFactor = Grounded ? Antislipperiness : AntislipperinessInAir;

        // Subtract friction
        float FrictionFactor = Mathf.Max(GroundVelocity.magnitude, 1);
        float Friction = Mathf.Min(GroundVelocity.magnitude, FrictionFactor * SlippyFactor * Time.deltaTime);
        GroundVelocity -= Friction * GroundVelocity.normalized;

        // Add player input momentum
        float TargetSpeed = MovementSpeed; // Tweak this to enable running or stuff
        Vector3 Move = transform.forward * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal");
        if (Move.magnitude > 0) {
            float CurrentSpeed = Vector3.Dot(Move, GroundVelocity);
            float SpeedDiff = TargetSpeed - CurrentSpeed;
            float Acceleration = Mathf.Min(SpeedDiff, TargetSpeed * SlippyFactor * Time.deltaTime);
            GroundVelocity += Move * Acceleration;
        }

        Character.Move((GroundVelocity + FallingVelocity * Vector3.up) * Time.deltaTime);
    }
}
