using System;
using UnityEngine;

public class PlatformerController : MonoBehaviour
{
    enum PlayerState
    {
        Crouching, Running, Walking, Dashing, Rolling, Attacking, Jumping, Dead, Idle  
    }
    
    [SerializeField] private new Rigidbody2D rigidbody2D; 
    [SerializeField] private new Collider2D collider;
    [SerializeField] private float moveSpeed;
    [SerializeField] private float crouchMultiplier, sprintMultiplier;
    [SerializeField] private float jumpForce,dashSpeed;
    [SerializeField] private LayerMask groundMask;
    [SerializeField] private Transform spawnPoint;
    private float _horizontal, _vertical,_currentSpeed; 
    private PlayerState _state = PlayerState.Idle;
    private SpriteRenderer _sp;
    private Vector2 _velocity;
    private bool _isDead;
    private bool _dashTrigger, _jumpTrigger;
    private float _lastDash, _lastJump;
    [SerializeField] private float  dashCooldown, jumpCooldown = 2f;
    private void Awake()
    {
        rigidbody2D = gameObject.GetComponent<Rigidbody2D>();
        _sp = gameObject.GetComponentInChildren<SpriteRenderer>();
        collider = gameObject.GetComponent<Collider2D>();
        _lastDash = 0f;
        _lastJump = 0f;
    }

    private void Start()
    {
        if (spawnPoint)
        {
            transform.position = spawnPoint.position;
        }
    }

    private void Update()
    {
        if (Input.GetButton("Dash")) _dashTrigger = true;
        if (Input.GetButton("Jump") || Input.GetAxis("Vertical") > 0f) _jumpTrigger = true;
        
    }

    private void FixedUpdate()
    {
        if (_isDead)
        {
            _state = PlayerState.Dead;
            return;
        }
        
        Controls();
        //Debug.Log("Player state: " + _state);
        AnimationController();
    }

    private void Controls()
    {
        //  ************************** Velocity lock zone **************************
        _velocity = rigidbody2D.velocity;
        _horizontal = Input.GetAxisRaw("Horizontal");
        _vertical = Input.GetAxisRaw("Vertical");
        bool isGrounded=Physics2D.IsTouchingLayers(collider, groundMask);
        
        // Movement behaviour
        _sp.flipX = _horizontal < 0; // Flip the sprite to face the direction
        _velocity = new Vector2(_horizontal * _currentSpeed,_velocity.y);
        rigidbody2D.velocity = _velocity;
        
        
        StateManager(isGrounded);
        Dash(_horizontal);
        Jump(isGrounded);

    }

    private void Dash(float direction) // Needs to be replaced by event in update
    {
        if(!_dashTrigger) return;
        if (Time.time - _lastDash < dashCooldown) return;

        Debug.Log("Dash!");
        
        _lastDash = Time.time;
        rigidbody2D.AddForce(Vector2.right * (dashSpeed * direction), ForceMode2D.Impulse);
        _dashTrigger = false;

    }
    private void Jump(bool isGrounded)
    {

        if (!isGrounded) return;
        if (!_jumpTrigger) return;
        if (Time.time - _lastJump < jumpCooldown) return;
        
        _lastJump = Time.time;  
        rigidbody2D.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
        _jumpTrigger = false;

    }

    private void StateManager(bool isGrounded)
    {
        //State Manager
        if (_horizontal != 0)
        {
            if (Input.GetButton("Run"))
            {
                _currentSpeed = moveSpeed * sprintMultiplier;
                _state = PlayerState.Running;
            }
            else
            {
                _currentSpeed = moveSpeed;
                _state = PlayerState.Walking;
            }
        }
        else
        {
            _state = PlayerState.Idle;
        }
        if (Input.GetButton("Crouch"))
        {
            _currentSpeed = moveSpeed * crouchMultiplier;
            _state = PlayerState.Crouching;
        }
        
        if (!isGrounded)
        {
            _state = PlayerState.Jumping; // Jump state is prioritized    
        }
        if (Input.GetButtonDown("Dash"))
        {
            _state = PlayerState.Dashing;
        }
    }

    void AnimationController() // Animation switch function to change between stances 
    {
        switch (_state)
        {
            case PlayerState.Crouching:
                break;
            case PlayerState.Running:
                break;
            case PlayerState.Walking:
                break;
            case PlayerState.Jumping:
                break;
            case PlayerState.Dead:
                break;
            case PlayerState.Idle:
                break;
            case PlayerState.Dashing:
                break;
            default:
                throw new Exception("Unknown state");
        }
    }

    private void Kill()
    {
        _isDead = true; 
    }

    private void Resurrect()
    {
        _isDead  = false;
    }
}
