using System;
using System.Collections;
using DG.Tweening;
using ObjectsPool;
using UnityEngine;
using UnityEngine.SceneManagement;

public class PlayerController : MonoBehaviour
{
    
    public static Action Win;
    public static Action<bool> BlockMovement;
    public static Action<Vector3> ShowCircleParticle;
    
    [SerializeField] private float speed = 10;
    [SerializeField] private float jumpForce = 10;
    [SerializeField] private int dubbleJumps;
    [SerializeField] private int dubbleJumpsStart = 1;
    [SerializeField] private float groundCheckRadius = .2f;
    [SerializeField] private Transform groundCheck;
    [SerializeField] private Transform bulletSpawnPoint;
    [SerializeField] private Bullet bulletPrefab;
    [SerializeField] private CircleParticle circleParticlePrefab;
    [SerializeField] private LayerMask groundMask;
    [SerializeField] private GameObject closedFace;
    
    [SerializeField] private CanvasGroup winPanel;

    [Header("AudioClips")]
    [SerializeField] private AudioClip jumpSfx;
    [SerializeField] private AudioClip attackSfx;
    
    private GameObjectPool _bulletPool;
    private GameObjectPool _circleParticlesPool;
    private bool _movementBlocked;
    private bool _facingRight = true;
    private bool _faceClosed = true;
    private float _moveInput;
    private Rigidbody2D _rb;
    
    

    void Start()
    {
        _bulletPool = new GameObjectPool(bulletPrefab, 10);
        _circleParticlesPool = new GameObjectPool(circleParticlePrefab, 10);
        _rb = GetComponent<Rigidbody2D>();
        dubbleJumps = dubbleJumpsStart;
        BlockMovement += SetBlockMovement;
        ShowCircleParticle += PlayCircleParticle;
        Win += LevelComplete;
    }

    private void OnDestroy()
    {
        BlockMovement -= SetBlockMovement;
        ShowCircleParticle -= PlayCircleParticle;
        Win -= LevelComplete;
    }

    void Update()
    {
        _moveInput = Input.GetAxisRaw("Horizontal");

        if (Input.GetKeyDown(KeyCode.C) || Input.GetKeyDown(KeyCode.Space)) Jump();
        if (Input.GetKeyDown(KeyCode.V) || Input.GetKeyDown(KeyCode.E)) Attack();
        
        Flip();
    }

    private void FixedUpdate()
    {
        Move();
        if (IsGround())
        {
            dubbleJumps = dubbleJumpsStart;
        }
    }

    private void Move()
    {
        _rb.velocity = _movementBlocked ? Vector2.zero : new Vector2(_moveInput * speed, _rb.velocity.y);
    }

    private void Jump()
    {

        if (_movementBlocked) return;
        if (dubbleJumps == 0) return;
        dubbleJumps--;
        SoundManager.PlaySFX?.Invoke(jumpSfx);
        _rb.velocity = new Vector2(_rb.velocity.x, 0);
        _rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
    }

    private void SetBlockMovement(bool blocked)
    {
        _movementBlocked = blocked;
    }

    private bool IsGround()
    {
        return Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundMask);
    }

    private void Flip()
    {
        if (_movementBlocked) return;
        if (_facingRight && _moveInput < 0 || !_facingRight && _moveInput > 0)
        {
            _facingRight = !_facingRight;
            transform.localEulerAngles = new Vector2(0, _facingRight ? 0 : 180);
        }
    }

    private void Attack()
    {
        if (_movementBlocked) return;
        PoolObject newBullet = _bulletPool.Get();
        newBullet.transform.localEulerAngles = transform.localEulerAngles;
        newBullet.SetObject(bulletSpawnPoint.position, _bulletPool);
        
        SoundManager.PlaySFX?.Invoke(attackSfx);
        //PlayCircleParticle(bulletSpawnPoint.position);
        StartCoroutine(FaceAnimation());
    }

    private IEnumerator FaceAnimation()
    {
        if (!_faceClosed) yield break;
        _faceClosed = false;
        closedFace.SetActive(false);
        
        yield return new WaitForSeconds(.15f);

        closedFace.SetActive(true);
        _faceClosed = true;
    }

    private void PlayCircleParticle(Vector3 spawnPosition)
    {
        PoolObject newCircleParticle = _circleParticlesPool.Get();
        newCircleParticle.SetObject(spawnPosition, _circleParticlesPool);
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
    }

    void LevelComplete()
    {
        StartCoroutine(LevelCompleteRoutine());
    }
    private IEnumerator LevelCompleteRoutine()
    {
        _movementBlocked = true;
        winPanel.DOFade(1, 1.5f);
        yield return new WaitForSeconds(1.5f);
        SceneManager.LoadScene(0);
    }
}
