using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

[RequireComponent(typeof(NavigateToTransform))]
public class Enemy : MonoBehaviour, TargetWithLifeThatNotifies.IDeathNotifiable
{
    [Header("Attack info")]
    [SerializeField] protected LayerMask targetLayers = Physics.DefaultRaycastLayers;
    [SerializeField] float horizontalRange = 1f;
    [SerializeField] float Damage = 1f;

    [SerializeField] Animator animator;
    SpriteRenderer Spr;

    NavigateToTransform navigateToTransform;

    [SerializeField] Transform currentTarget = null;
    GameObject Tower = null;
    Transform[] TowerColliders;
    [SerializeField] Transform TowerTransform = null;

    [Header("On death drops")]
    [SerializeField] GameObject DropItem;

    Sight sight;

    enum State
    {
        Seek,
        Attack,
        Die,
        ToTower,
    };

    public enum BehaviourType
    {
        Valiant,
        Runner,
        Guardian,
    }

    public BehaviourType behaviourType = BehaviourType.Valiant;
    [SerializeField] State state = State.ToTower;

    private void Awake()
    {
        navigateToTransform = GetComponent<NavigateToTransform>();
        Tower = GameObject.FindGameObjectWithTag("Tower");

        Spr = GetComponentInChildren<SpriteRenderer>();
        sight = GetComponent<Sight>();

    }
    void Start()
    {
        TowerColliders = Tower.GetComponentsInChildren<Transform>();
        state = State.ToTower;
    }

    void Update()
    {
        if(behaviourType != BehaviourType.Guardian)
        {
            UpdateCurrentTarget();
        }

        switch (state)
        {
            case State.Seek:
                if (currentTarget == null)
                {
                    state = State.ToTower;
                }
                else
                {
                    GoTo(currentTarget);
                    if (IsInAttackRange())
                    {
                        state = State.Attack;
                        GoTo(null);
                    }
                }
                break;

            case State.Attack:
                UpdateAttack();
                break;

            case State.ToTower:
                if (currentTarget != null && behaviourType != BehaviourType.Guardian)
                {
                    state = State.Seek;
                }
                else
                {
                    if(TowerTransform == null)
                    {
                        UpdateTowerTransform();
                    }
                    if (TowerReached())
                    {
                        state = State.Attack;
                        GoTo(null);
                    }
                    else
                    {
                        GoTo(TowerTransform);
                    }
                }
                break;

            case State.Die:
                break;
        }
    }

    void UpdateCurrentTarget()
    {
        if (behaviourType != BehaviourType.Runner && TowerReached()/* && currentTarget != null*/)
        {
            return;
        }

        if (/*currentTarget == null && */sight.collidersInSight.Count > 0)
        {
            Collider2D nearestCollider = sight.collidersInSight[sight.collidersInSight.Count - 1];
            foreach(Collider2D c in sight.collidersInSight)
            {
                if(c == null || nearestCollider == null)
                {
                    continue;
                }
                BaseAlly targetAlly = c.GetComponentInChildren<BaseAlly>();
                if (targetAlly)
                {
                    bool FindAnotherIfIsAttacked = (targetAlly.IsBeingAttacked && (Random.Range(0, 9) < 5));
                    if (FindAnotherIfIsAttacked)
                    {
                        continue;
                    }
                    else
                    {
                        float newDistance = Vector3.Distance(this.transform.position, c.transform.position);
                        if (newDistance <= Vector3.Distance(this.transform.position, nearestCollider.transform.position))
                        {
                            nearestCollider = c;
                        }
                    }
                }

            }

            if(nearestCollider != null)
                currentTarget = nearestCollider.transform;
        }

    }

    void UpdateTowerTransform()
    {
        TowerTransform = TowerColliders[0].transform;

        foreach(Transform PC in TowerColliders)
        {
            float newDistance = Vector3.Distance(this.transform.position, PC.transform.position);

            if(newDistance <= Vector3.Distance(this.transform.position, TowerTransform.position))
            {
                TowerTransform = PC.transform;
            }

        }
    }

    public void Attack()
    {
        TargetBase targetBase = null;
        if (currentTarget)
        {
            targetBase = currentTarget.GetComponentInChildren<TargetBase>();
        }
        else if (Tower != null)
        {
            if (Tower.GetComponent<TargetBase>())
                targetBase = Tower.GetComponent<TargetBase>();
        }
        Debug.Log("Ataco a plantuqie");
        targetBase?.NotifySwing(Damage);
        
        /*-------------------------------------------- ATAQUE EN AREA --------------------------------------------------

        Vector2 Extents = new Vector2(horizontalRange, verticalRange);
        Vector2 AttackPoint;

        if(currentTarget)
        {
            AttackPoint = (currentTarget.position + transform.position) / 2;
        }
        else
        {
            AttackPoint = transform.position;
        }

        Collider2D collider = Physics2D.OverlapBox(AttackPoint, Extents, 0, targetLayers);
        
        if (collider != null)
        {
            TargetBase targetBase = collider.GetComponent<TargetBase>();
            targetBase?.NotifySwing(Damage);
        }
        
         --------------------------------------------------------------------------------------------------------------*/
    }

    void UpdateAttack()
    {
        animator.SetBool("Attack", true);
        //Attack();

        if (!IsInAttackRange() && !TowerReached())
        {
            state = State.Seek;
            animator.SetBool("Attack", false);
            if (currentTarget != null)
                GoTo(currentTarget);
            else
                state = State.ToTower;
        }
    }

    bool IsInAttackRange()
    {
        if (currentTarget != null)
            return Vector3.Distance(transform.position, currentTarget.transform.position) < (horizontalRange * 1.5);
        else
            return false;
    }

    bool TowerReached()
    {
        if (TowerTransform != null)
            return Vector3.Distance(transform.position, TowerTransform.position) < (horizontalRange * 1.5);
        else
            return false;
    }

    void GoTo(Transform targetTransform)
    {
        if(targetTransform != null)
        {
            if (targetTransform.position.x > this.transform.position.x)
            {
                Spr.flipX = true;
            }
            else
            {
                Spr.flipX = false;
            }
        }
        navigateToTransform.transformGoTo = targetTransform;
    }

    public void SlowMovement(float Multiplier, float TimeSlowed)
    {
        StartCoroutine(ApplySlowMovement(Multiplier, TimeSlowed));
    }

    IEnumerator ApplySlowMovement(float Multiplier, float TimeSlowed)
    {
        NavMeshAgent agent = GetComponent<NavMeshAgent>();
        if (agent)
        {
            agent.speed *= Multiplier;
            yield return new WaitForSeconds(TimeSlowed);
            agent.speed /= Multiplier;
        }

    }

    void TargetWithLifeThatNotifies.IDeathNotifiable.NotifyDeath()
    {
        if (state != State.Die)
        {
            state = State.Die;

            animator.enabled = false;
            GetComponent<CircleCollider2D>().enabled = false;
            GetComponent<NavMeshAgent>().enabled = false;
            GetComponent<NavigateToTransform>().enabled = false;
            Spr.enabled = false;

            Invoke("Death", 3f);
        }
    }

    private void Death()
    {
        Destroy(gameObject);
    }
}
