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

public class PlayerController : MonoBehaviour
{
    [Header("Object References")]
    public Rigidbody2D rb;

    [Header("Horizontal Movement")]
    public float moveSpeed = 10f;

    [Header("Vertical Movement")]
    public float jumpForce = 10f;

    [Header("Grounded")]
    public Transform groundCheck;
    public LayerMask groundLayer;
    public float groundRadius = 0.2f;
    bool isGrounded = false;

    private float mx = 0f;
    bool isFacingRight = true;

    [Header("Wall Jump")]
    public float wallJumpTime = 0.2f;
    public float wallSlideSpeed = 0.3f;
    public float wallDistance = 0.5f;
    public float wallJumpForce;
    bool isWallSliding = false;
    RaycastHit2D wallCheckHit;
    bool wallJumped;
    float jumpTime;

    [Header("Dash")]
    public float dashDistance = 15f;
    bool isDashing;
    public float coolDownTime = 2f;
    float nextDashTime = 0f;
    float doubleTapTime;
    KeyCode lastKeyCode;

    int jumpCounter = 1;

    // Start is called before the first frame update
    void Start()
    {

    }

    private void Update()
    {

        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            Jump(jumpForce);
        } else if (Input.GetButtonDown("Jump") && isWallSliding)
        {
            if (isWallSliding && isFacingRight)
            {
                Jump(wallJumpForce);
                rb.velocity = new Vector2(rb.velocity.x - 5, rb.velocity.y);
            } else if (isWallSliding && !isFacingRight)
            {
                Jump(wallJumpForce);
                rb.velocity = new Vector2(rb.velocity.x + 5, rb.velocity.y);
            }
        }
        // Dashing Left
        if (Input.GetKeyDown(KeyCode.A))
        {
            if (doubleTapTime > Time.time && lastKeyCode == KeyCode.A && Time.time > nextDashTime)
            {
                StartCoroutine(Dash(-1f));
                nextDashTime = Time.time + coolDownTime;
            } else
            {
                doubleTapTime = Time.time + 0.3f;
            }

            lastKeyCode = KeyCode.A;
        }

        // Dashing Right
        if (Input.GetKeyDown(KeyCode.D))
        {
            if (doubleTapTime > Time.time && lastKeyCode == KeyCode.D && Time.time > nextDashTime)
            {
                StartCoroutine(Dash(1f));
                nextDashTime = Time.time + coolDownTime;
            }
            else
            {
                doubleTapTime = Time.time + 0.3f;
            }

            lastKeyCode = KeyCode.D;
        }
    }

    void FixedUpdate()
    {
        mx = Input.GetAxis("Horizontal");

        if (mx < 0)
        {
            isFacingRight = false;
            transform.localScale = new Vector2(-1, transform.localScale.y);
        }
        else if (mx > 0)
        {
            isFacingRight = true;
            transform.localScale = new Vector2(1, transform.localScale.y);
        }
        if (!isDashing)
        {
            rb.velocity = new Vector2(mx * moveSpeed, rb.velocity.y);
        }
        bool touchingGround = Physics2D.OverlapCircle(groundCheck.position, groundRadius, groundLayer);

        if (touchingGround)
        {
            isGrounded = true;
            jumpTime = Time.time + wallJumpTime;
        }
        else if (jumpTime < Time.time)
        {
            isGrounded = false;
        }

        // Wall Jump
        if (isFacingRight)
        {
            wallCheckHit = Physics2D.Raycast(transform.position, new Vector2(wallDistance, 0), wallDistance, groundLayer);
           //Debug.DrawRay(transform.position, new Vector2(wallDistance, 0f), Color.blue);
        }
        else
        {
            wallCheckHit = Physics2D.Raycast(transform.position, new Vector2(-wallDistance, 0), wallDistance, groundLayer);
           //Debug.DrawRay(transform.position, new Vector2(-wallDistance, 0f), Color.blue);
        }

        if (wallCheckHit && !isGrounded && wallJumped)
        {
            isWallSliding = true;
            jumpTime = Time.time + wallJumpTime;
            wallJumped = false;
        }
        else if (jumpTime < Time.time)
        {
            isWallSliding = false;
        }

        if (isWallSliding)
        {
            rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, wallSlideSpeed, float.MaxValue));
        }
    }

    void Jump(float jumpingForce)
    {
        rb.velocity = new Vector2(rb.velocity.x, jumpingForce);
    }

    IEnumerator Dash(float direction)
    {
        isDashing = true;
        if (isFacingRight)
        {
            rb.AddForce(new Vector2(dashDistance, 0f), ForceMode2D.Impulse);
            rb.velocity = new Vector2(rb.velocity.x, 0f);
        } else if (!isFacingRight)
        {
            rb.AddForce(new Vector2(-dashDistance, 0f), ForceMode2D.Impulse);
            rb.velocity = new Vector2(rb.velocity.x, 0f);
        }
        float gravity = rb.gravityScale;
        rb.gravityScale = 0;
        yield return new WaitForSeconds(0.4f);
        isDashing = false;
        rb.gravityScale = gravity;
        rb.velocity = new Vector2(mx * moveSpeed, rb.velocity.y);
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        wallJumped = true;
    }

}