using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;

public class Puertas : MonoBehaviour
{
    [HideInInspector]
    public enum PuertaTipo
    {
        Puerta = 0,
        Trampilla = 1,
        Rejilla = 2
    };
    [SerializeField]
    private PuertaTipo puertaTipo;
    [SerializeField]
    private GameObject PointA;
    [SerializeField]
    private List<GameObject> MascarasA;

    [SerializeField]
    private GameObject PointB;
    [SerializeField]
    private List<GameObject> MascarasB;

    GameObject player;
    private bool isPlayerNear;

    #region CALCULO DE PROXIMIDAD
    private void OnTriggerEnter2D(Collider2D _col)
    {
        if (_col.CompareTag("Player"))
        {
            player = _col.gameObject;
            PlayerEnter();
        }
    }
    private void OnTriggerExit2D(Collider2D _col)
    {
        if (_col.CompareTag("Player"))
        {
            PlayerExit();
        }
    }
    /// <summary>
    /// Funcion que se activa cuando el jugador sale de rango, aqui ira toda
    /// la logica que desactive la interfaz y los objetos.
    /// </summary>
    private void PlayerExit()
    {
        isPlayerNear = false;

        this.transform.GetChild(0).GetChild(0).gameObject.SetActive(false);
        this.transform.GetChild(0).GetChild(1).gameObject.SetActive(false);
    }
    /// <summary>
    /// Funcion que se activa cuando el jugador entra en rango y calcula
    /// de que punto está mas cerca, activando así el punto pertinente.
    /// </summary>
    private void PlayerEnter()
    {
        isPlayerNear = true;

        float distanceA = Vector2.Distance(player.transform.position, PointA.transform.position);
        float distanceB = Vector2.Distance(player.transform.position, PointB.transform.position);

        if (distanceA <= distanceB) OnPointAEnter();
        else OnPointBEnter();
    }
    /// <summary>
    /// Funcion activa la interfaz y funciones cuando el personaje entra
    /// en rango y está cerca del punto "A".
    /// </summary>
    private void OnPointAEnter()
    {
        this.transform.GetChild(0).GetChild(0).gameObject.SetActive(true);
        this.transform.GetChild(0).GetChild(1).gameObject.SetActive(false);
    }
    /// <summary>
    /// Funcion activa la interfaz y funciones cuando el personaje entra en
    /// rango y está cerca del punto "B".
    /// </summary>
    private void OnPointBEnter()
    {
        this.transform.GetChild(0).GetChild(0).gameObject.SetActive(false);
        this.transform.GetChild(0).GetChild(1).gameObject.SetActive(true);
    }
    #endregion FIN CALCULO DE PROXIMIDAD
    #region INTERCAMBIO DE ESCENARIOS
    private void Update()
    {
        if(isPlayerNear)
        {
            if (Input.GetKeyDown(KeyCode.E)) PlayerClick();
        }
    }
    /// <summary>
    /// Funcion que se activa cuando el jugador esta en rango y pulsa el boton
    /// de accion.
    /// </summary>
    private void PlayerClick()
    {
        this.transform.GetChild(0).GetChild(0).gameObject.SetActive(false);
        this.transform.GetChild(0).GetChild(1).gameObject.SetActive(false);

        float distanceA = Vector2.Distance(player.transform.position, PointA.transform.position);
        float distanceB = Vector2.Distance(player.transform.position, PointB.transform.position);

        player.GetComponent<PlayerMove>().enabled = false;
        player.GetComponent<CapsuleCollider2D>().enabled = false;
        player.GetComponent<Rigidbody2D>().velocity = Vector2.zero;
        player.GetComponent<Rigidbody2D>().isKinematic = true;

        if (distanceA <= distanceB) StartCoroutine( OnClick(PointA, PointB, MascarasA, MascarasB) );
        else StartCoroutine( OnClick(PointB, PointA, MascarasB, MascarasA) );
    }
    private IEnumerator OnClick(GameObject PointA, GameObject PointB, List<GameObject> MascarasA = null, List<GameObject> MascarasB = null)
    {
        // DESACTIVAR TODAS LAS MASCARAS
        foreach (GameObject g in MascarasA)
        {
            g.SetActive(false);
        }
        foreach (GameObject g in MascarasB)
        {
            g.SetActive(false);
        }
        // MOVIMIENTO A PUNTO_A
        while ((Vector2)player.transform.position != (Vector2)PointA.transform.position)
        {
            if (Vector2.Distance(player.transform.position, new Vector2(PointA.transform.position.x, player.transform.position.y)) > 0.2f)
            {
                MoveTo(new Vector2(PointA.transform.position.x, player.transform.position.y));
            }
            else
            {
                player.transform.position = (Vector2)PointA.transform.position;
            }
            yield return new WaitForEndOfFrame();
        }
        if(this.puertaTipo.Equals(PuertaTipo.Puerta))
        {
            if(player.TryGetComponent(out Animator an))
            {
                if(an.GetInteger("State") != 1)
                {
                    an.SetInteger("State", 1);
                    if (player.TryGetComponent(out Transformacion tr))
                    {
                        player.GetComponent<CapsuleCollider2D>().enabled = true;
                        tr.HumanToSlime();
                        player.GetComponent<Rigidbody2D>().isKinematic = false;
                    }
                    yield return new WaitForSeconds(1.2f);
                }
            }

            an.SetInteger("State", 2);
            yield return new WaitForSeconds(1f);
            player.GetComponent<Rigidbody2D>().isKinematic = true;
            player.GetComponent<CapsuleCollider2D>().enabled = false;
        }
        // MOVIMIENTO A PUNTO_B
        while ((Vector2)player.transform.position != (Vector2)PointB.transform.position)
        {
            if (Vector2.Distance(player.transform.position, new Vector2(PointB.transform.position.x, player.transform.position.y)) > 0.2f)
            {
                MoveTo( new Vector2(PointB.transform.position.x, player.transform.position.y) );
            }
            else
            {
                player.transform.position = (Vector2)PointB.transform.position;
            }
            yield return new WaitForEndOfFrame();
        }

        if (this.puertaTipo.Equals(PuertaTipo.Puerta))
        {
            if (player.TryGetComponent(out Animator an))
            {
                if (an.GetInteger("State") != 1)
                {
                    an.SetInteger("State", 1);
                }
            }
        }
        // ACTIVAR LAS MASCARAS DE A
        foreach (GameObject g in MascarasA)
        {
            g.SetActive(true);
        }
        ReactivatePlayer();
    }
    /// <summary>
    /// Funcion que mueve al personaje hacia el punto "Position" pasado como argumento.
    /// </summary>
    /// <param name="Position"></param>
    private void MoveTo(Vector2 Position)
    {
        float fraction = 0.03f;
        Vector2 newPosition = Vector2.Lerp(player.transform.position, Position, fraction);
        player.transform.position = newPosition;
    }
    /// <summary>
    /// Reactiva los movimientos, collider y fisicas del jugador.
    /// </summary>
    private void ReactivatePlayer()
    {
        player.GetComponent<PlayerMove>().enabled = true;
        player.GetComponent<CapsuleCollider2D>().enabled = true;
        player.GetComponent<Rigidbody2D>().isKinematic = false;
    }
    #endregion FIN INTERCAMBIO ESCENARIOS
}
