using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;


public class EnemyBehavior : MobBase
{
    public override LevelObjectFaction ObjectFaction { get { return LevelObjectFaction.Human; } }
    public override LevelObjectType ObjectType { get { return LevelObjectType.Knight; } }

    private Transform Tower;
    private Transform Necromancer;
    private Transform fleeSpawner;
    public float fleeSpeed = 1.5f;
    public AudioSource attackSound;
    private bool isFleeing = false;
    private bool attacking = false;
    private float attackTimeout;
    private SpriteRenderer knightSpriteRenderer;

    Animator animator;

    //some flags to check when certain animations are playing
    bool isIdle = false;
    bool isWalking = false;

    //animation states - the values in the animator conditions
    const int STATE_IDLE = 0;
    const int STATE_ATTACK = 1;
    int _currentAnimationState = STATE_IDLE;

    LevelObjectType[] attackPreference =
    {
        LevelObjectType.Wall,
        LevelObjectType.Zombie,
        LevelObjectType.Tower,
        LevelObjectType.Player,
    };

    void Awake()
    {
        Init();
    }
    // Use this for initialization
    public override void Init()
    {
        base.Init();
        EventManager.SubscribeSunset(RunAway);
        Tower = GameObject.Find("Tower").transform;
        Necromancer = GameObject.Find("Necromancer").transform;
        knightSpriteRenderer = GetComponent<SpriteRenderer>();
        animator = this.GetComponent<Animator>();
        changeState(STATE_IDLE); // Default to idle state
        isFleeing = false;
        attacking = false;
    }

    protected override void TearDown()
    {
        base.TearDown();
        EventManager.UnsubscribeSunset(RunAway);
    }


    // Update is called once per frame
    void Update()
    {
        //Keep this line first in the Update method.
        if (paused) return;

        if (isFleeing)
        {
            FleeAction();
            return;
        }

        if (attacking)
        {
            //checked for timeout reset
            if(Time.time >= attackTimeout)
            {
                attacking = false;
            }
        }

        var enemyContacts = ContactObjects.Where(o => o.ObjectFaction == LevelObjectFaction.Zombie);
        if(enemyContacts.Any())
        {
            if (!attacking)
            {
                if (AttackAction(enemyContacts)) return;
            }
            return;
        }
        AdvanceAction();
    }

    void FleeAction()
    {
        //Using Y of necromancer makes them less bumpy so they stop trying to float to the Tower
        Vector3 displacement = new Vector3(fleeSpawner.position.x, Necromancer.position.y, 0f) - transform.position;
        if (transform.position.x - fleeSpawner.position.x < 1)
            knightSpriteRenderer.flipX = true;
        else
            knightSpriteRenderer.flipX = false;
        displacement = displacement.normalized;
        if (Vector2.Distance(fleeSpawner.position, transform.position) > 1.0f)
        {
            transform.position += (displacement * fleeSpeed * Time.deltaTime);
        }
        else
        {
            Kill();
            return;
        }
    }

    bool AttackAction(IEnumerable<LevelObjectBase> enemyContacts)
    {
        foreach (var objType in attackPreference)
        {
            var target = enemyContacts.FirstOrDefault(o => o.ObjectType == objType && !o.Destroyed);
            if (target != null)
            {
                attacking = true;
                attackTimeout = Time.time + AttackCooldownInSeconds;
                animator.SetTrigger("KnightAttack");
                attackSound.Play();
                target.TakeDamage(this, Damage);
                return true;
            }
        }
        return false;
    }
    void AdvanceAction()
    {
        //Using Y of necromancer makes them less bumpy so they stop trying to float to the Tower
        Vector3 displacement = new Vector3(Tower.position.x, Necromancer.position.y, 0f) - transform.position;
        if (transform.position.x - Tower.position.x < 1)
            knightSpriteRenderer.flipX = true;
        else
            knightSpriteRenderer.flipX = false;
        displacement = displacement.normalized;
        if (Vector2.Distance(Tower.position, transform.position) > 1.0f)
        {
            transform.position += (displacement * Speed * Time.deltaTime);
        }
    }

    void RunAway()
    {
        isFleeing = true;
        attacking = false;
        GameObject[] goArray = GameObject.FindGameObjectsWithTag("Spawn");
        fleeSpawner = GetClosestObjectType(goArray);
    }

    Transform GetClosestObjectType(GameObject[] objectType)
    {
        Transform bestTarget = null;
        float closestDistanceSqr = Mathf.Infinity;
        Vector3 currentPosition = transform.position;
        foreach (GameObject potentialTarget in objectType)
        {
            Vector3 directionToTarget = potentialTarget.transform.position - currentPosition;
            float dSqrToTarget = directionToTarget.sqrMagnitude;
            if (dSqrToTarget < closestDistanceSqr)
            {
                closestDistanceSqr = dSqrToTarget;
                bestTarget = potentialTarget.transform;
            }
        }

        return bestTarget;
    }

    //void OnTriggerStay2D(Collider2D col)
    //{
    //    //Debug.LogWarning("CollisionEventGlobalAttackStat: " + Assets.GlobalVars.CanPlayerTakeDamage.ToString());
    //    //Debug.Log("Enemy coll");
        
    //    //// TODO: MAke a switch statement to apply attack heirarchy.  Priority of attack will be WAll>Zombie>Tower>Necro
    //    //if(col.tag == "Wall" && attacking)
    //    //{
    //    //    animator.SetTrigger("KnightAttack");
    //    //    StartCoroutine("DisableDamage", false);
    //    //}
    //    //else if(col.tag == "Ally" && attacking)
    //    //{
    //    //    animator.SetTrigger("KnightAttack");
    //    //    StartCoroutine("DisableDamage", false);
    //    //}
    //    //else if (col.tag == "Tower" && attacking)
    //    //{
    //    //    animator.SetTrigger("KnightAttack");
    //    //    StartCoroutine("DisableDamage", false);
    //    //}
    //    //else if (col.name == "Necromancer" && attacking && Assets.GlobalVars.CanPlayerTakeDamage)
    //    //{
    //    //    animator.SetTrigger("KnightAttack");
    //    //    bool knockRight = col.transform.position.x > transform.position.x;
    //    //    col.SendMessage("receiveDamage", knockRight, SendMessageOptions.DontRequireReceiver);
    //    //    StartCoroutine("DisableDamage", true);
    //    //}
    //}

    //IEnumerator DisableDamage(bool isNecromancer)
    //{
    //    attacking = false; // Monster can't attack
    //    if(isNecromancer)
    //        Assets.GlobalVars.CanPlayerTakeDamage = false; // Player can't take damage

    //    yield return new WaitForSeconds(AttackCooldownInSeconds);
    //    attacking = true; // Monster can attack
        
    //    if(isNecromancer)
    //        Assets.GlobalVars.CanPlayerTakeDamage = true; // Player can take damage
    //}

    void changeState(int state)
    {

        if (_currentAnimationState == state)
            return;

        switch (state)
        {

            case STATE_IDLE:
                animator.SetInteger("State", STATE_IDLE);
                break;

            case STATE_ATTACK:
                animator.SetInteger("State", STATE_ATTACK);
                break;

        }

        _currentAnimationState = state;
    }
}

