using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField]
    [Range(1,2)]
    public int Number = 1;
    public PlayerStats Stats;
    public PlayerActions InputActions;
    public BaseAttack AttackReference;

    public BaseAttack AttackInstance { get; private set; }

    public float _initialScale;

    #region References
    public Transform Transform { get; private set; }
    public Rigidbody2D Rigidbody { get; private set; }
    private float _radius;
    public Transform ShootingPoint { get; private set; }
    private StateMachine _stateMachine;
    private SpriteRenderer _spriteRenderer;
    public PlayerSoundManager SoundManager { get; private set; }
    #endregion

    void Awake()
    {
        Transform = GetComponent<Transform>();
        Rigidbody = GetComponent<Rigidbody2D>();
        _radius = GetComponent<CircleCollider2D>().radius;
        ShootingPoint = Transform.FindChild("ShootingPoint");
        _spriteRenderer = Transform.GetComponentInChildren<SpriteRenderer>();
        SoundManager = GetComponent<PlayerSoundManager>();
    }

    void Start()
    {
        InputActions = new PlayerActions(Number);
        _stateMachine = new StateMachine();
        _stateMachine.ChangeState(new ActiveState(this));

        AttackInstance = Instantiate(AttackReference, ShootingPoint.position, Quaternion.identity, ShootingPoint) as BaseAttack;

        AttackInstance.transform.right = ShootingPoint.right;
        _initialScale = Transform.localScale.x;
    }

    void Update()
    {
        _stateMachine.Update();
    }

    void FixedUpdate()
    {
        // Clamp speed
        if (Rigidbody.velocity.magnitude > Stats.MaxSpeed)
            Rigidbody.velocity = Rigidbody.velocity.normalized * Stats.MaxSpeed;
    }

    public void OnWaveCollision(float pushStrength)
    {
        RaycastHit2D hit = Physics2D.CircleCast(Transform.position, _radius + 0.01f, Transform.forward);

        Vector3 pushDirection = (Transform.position - (Vector3)hit.point).normalized;

        Rigidbody.AddForce(pushDirection * pushStrength);
    }

    private Tweener _chargeTween;
    private Tweener _shakeTween;

    public void OnChargeStarted()
    {
        float chargeTime = ((ChargeAttack)AttackInstance).ChargeTime;
        
        _chargeTween = Transform.DOScale(_initialScale * 1.2f, chargeTime).OnComplete(() =>
        {
            if (_shakeTween == null)
                _shakeTween = _spriteRenderer.transform.DOShakePosition(1, 0.09f, 100, 90, false, false).SetLoops(-1, LoopType.Restart).SetEase(Ease.Linear);
            else
                _shakeTween.Play();

            InputActions.VibrateDevice(0.35f);
        });
    }

    public void OnCooldownStarted()
    {
        _chargeTween.Pause();
        _chargeTween.Kill();
        _shakeTween.Pause();

        _spriteRenderer.transform.DOLocalMove(Vector3.zero, 0.1f).SetEase(Ease.Linear);

        _chargeTween = Transform.DOScale(Vector3.one * _initialScale, 0.25f).SetEase(Ease.OutElastic);

        InputActions.StopDeviceVibration();
    }

    public void Die()
    {
        _chargeTween.Kill();
        _shakeTween.Kill();

        EventDispatcher.Instance.Dispatch(new GameOverEvent(gameObject, Number == 1 ? 2 : 1));
        Rigidbody.velocity = Vector3.zero;
        SoundManager.PlayPopSound();

        Destroy(gameObject);
    }
}

[System.Serializable]
public struct PlayerStats
{
    public float TurnSpeed;
    public float MoveSpeed;
    public float MaxSpeed;
}