using System;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Serialization;


[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(Health))]
[RequireComponent(typeof(Statistics))]

public class Player : MonoBehaviour, IResettable, ICommandTranslator
{
    #region StateMachine

    public PlayerStateMachine PlayerStateMachine { get; private set; }

    #endregion

    #region Animation

    private Animator animator;
    [SerializeField] private AnimationCurve jumpDeltaYCurve;

    public AnimationCurve JumpDeltaYCurve
    {
        get { return jumpDeltaYCurve; }
    }

    public PlayerAnimator PlayerAnimator { get; private set; }

    #endregion

    #region PlayerComponents

    public PlayerData playerData;
    public IDamageable PlayerHealth { get; private set; }
    public Statistics PlayerStatictics { get; private set; }


    #endregion

    #region MovementControl

    [SerializeField] private LaneSystem laneSystem;

    public LaneSystem LaneSystem
    {
        get => laneSystem;
        private set => laneSystem = value;
    }


    public CharacterController CharacterController { get; private set; }
    public PlayerCollider PlayerCollider { get; private set; }

    #endregion

    public bool IsInvincible { get; private set; }
    public float InvincibilityTime { get; private set; } //PLAYER DATA ScriptableObject
    [SerializeField] private Boolean isPlayer2;
    [SerializeField] private Boolean isPlaying1VS1;
    public bool isDead = false;

    private void Awake()
    {
        playerData = GameSession.Instance.GetPlayerData();
        GameSession.Instance.AddCommandTranslator(this, isPlayer2);
        animator = GetComponent<Animator>();
        if (animator)
            PlayerAnimator = new PlayerAnimator(animator);
        CharacterController = GetComponent<CharacterController>();
        PlayerCollider = new PlayerCollider(CharacterController);
        PlayerHealth = GetComponent<IDamageable>();
        PlayerStatictics = GetComponent<Statistics>();
        PlayerStateMachine = new PlayerStateMachine(this);
        InvincibilityTime = playerData.InvincibilityTime;
    }

    private void OnEnable()
    {
        PlayerHealth.OnOutOfHealth += Die;
    }
    private void Start()
    {
        PlayerStateMachine.SetState(PlayerStateMachine.PlayerStartingIdleState);
    }


    private void Update()
    {
        PlayerStateMachine.Tick();
    }

    private void FixedUpdate()
    {
        PlayerStateMachine.FixedTick();
    }

    public float PendingAdditionalOffset { get; private set; }

    private void OnTriggerEnter(Collider other)
    {
        if (other.TryGetComponent(out IDamageDealer damageDealer)) //switch..case
        {
            if (IsInvincible)
                return;
            int damageAmount = 1;
            var damageableComponents = GetComponents<IDamageable>();
            foreach (var component in damageableComponents)
            {
                damageDealer.DealDamage(component, damageAmount);
            }

            StartCoroutine(GrantInvincibility());
        }

        if (other.TryGetComponent(out IObstacle obstacle)) //switch..case
        {
            obstacle.Impact();
        }
        else if (other.TryGetComponent(out ICollectable collectable))
        {
            collectable.Collect();
        }
    }

    private void Die()
    {
        isDead = true;
        PlayerStateMachine.SetState(PlayerStateMachine.PlayerDeadState);
        GameSession.Instance.UpdateScoreboard(new ScoreboardEntry(name, PlayerStatictics.Score));
        GameSession.Instance.HandlePlayerDeath(this); // Informe GameSession qu'un joueur est mort
        
        // PlayerStateMachine.SetState(PlayerStateMachine.PlayerDeadState);
        // GameSession.Instance.UpdateScoreboard(new ScoreboardEntry(name, PlayerStatictics.Score));
        // if (isPlaying1VS1)
        // {
        //     // SceneManager.LoadScene("DeathScreen1v1");
        //     SceneManager.LoadScene("Death1VS1");
        //
        // }
        // else
        // {
        //     SceneManager.LoadScene("Death1VS1");
        // }
        //
    }

    public IEnumerator GrantInvincibility()
    {
        IsInvincible = true;
        yield return new WaitForSeconds(InvincibilityTime);
        IsInvincible = false;
    }

    private void ReloadAnimator()
    {
        if (animator)
            PlayerAnimator = new PlayerAnimator(animator);
    }

    public void ResetToDefault()
    {
        PlayerStateMachine.SetState(null);
        PlayerStatictics.ResetToDefault();
        LaneSystem.ResetToDefault();
        Physics.SyncTransforms();
        ReloadAnimator();
    }

    public void TranslateCommand(ECommand command, PressedState state)
    {
        if (state.IsPressed)
        {
            switch (command)
            {
                case ECommand.RIGHT:
                case ECommand.RIGHT2:
                    PlayerStateMachine.IncreaseTargetLane();
                    break;
                case ECommand.LEFT:
                case ECommand.LEFT2:
                    PlayerStateMachine.DecreaseTargetLane();
                    break;
                case ECommand.UP:
                case ECommand.UP2:
                    PlayerStateMachine.SetState(PlayerStateMachine.PlayerJumpState);
                    break;
                case ECommand.DOWN:
                case ECommand.DOWN2:
                    PlayerStateMachine.SetState(PlayerStateMachine.PlayerSlideState);
                    break;
                default:
                    break;
            }
        }
    }

}
