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

public class DemonAI : MonoBehaviour
{
    public float MovementSpeed = 1;
    public float MaxSpeed = 5.0f;

    Weapon[] weapons;
    CharacterData ownCharacter;
    DemonController demonController;

    public int StartGlyphcount = 0;

    Vector2 dir;

    // Use this for initialization
    void Start()
    {
        weapons = GetComponentsInChildren<Weapon>();
        ownCharacter = GetComponent<CharacterData>();
        demonController = GetComponent<DemonController>();
        applySizeToGlyphCount(ownCharacter.GlyphStack.Count);
        StartGlyphcount = ownCharacter.GlyphStack.Count;
        StartCoroutine(doAIBehaviour());
    }

    void FixedUpdate()
    {
        if (rigidbody2D.velocity.sqrMagnitude > 0.1f * 0.1f)
        {
            if (Mathf.Abs(dir.x) > Mathf.Abs(dir.y))
            {
                if (dir.x < 0)
                {
                    demonController.Direction = DemonController.DemonDirection.Left;
                }
                else
                {
                    demonController.Direction = DemonController.DemonDirection.Right;
                }
            }
            else
            {
                if (dir.y < 0)
                {
                    demonController.Direction = DemonController.DemonDirection.Down;
                }
                else
                {
                    demonController.Direction = DemonController.DemonDirection.Up;
                }
            }
        }

    }

    IEnumerator doAIBehaviour()
    {
        while (true)
        {
            // search for character
            CharacterData characterToAttack = null;
            foreach (CharacterData character in CharacterManager.instance.characters)
            {
                if (character != ownCharacter && !character.isDead && (characterToAttack == null || character.Type != CharacterType.Player))
                {
                    characterToAttack = character;
                }

            }
            if (characterToAttack != null)
            {
                // attack character
                yield return StartCoroutine(attack(characterToAttack));
            }
            else
            {
                yield return new WaitForFixedUpdate();
            }
        }
    }

    IEnumerator attack(CharacterData character)
    {
        while (!character.isDead && !ownCharacter.isDead)
        {
            if (character.Type == CharacterType.Player)
            {
                // the demon rather attacks another demon than the player
                if (CharacterManager.instance.getNumberOfRegisteredCharacters(CharacterType.Demon) > 1)
                {
                    Debug.Log("there is another demon! we stop attacking the player");
                    stopAllAttacks();
                    yield break;
                }
            }
            // attack with all weapons that are in range and are ready
            Vector2 targetVector = new Vector2(character.transform.position.x - transform.position.x, character.transform.position.y - transform.position.y);
            bool needsToMove = false;
            float distToCharacterSquared = targetVector.sqrMagnitude;
            foreach (Weapon weapon in weapons)
            {
                distToCharacterSquared = Mathf.Max(0, distToCharacterSquared - (character.Scale * character.Scale));
                if (distToCharacterSquared < ownCharacter.Scale * weapon.Range * weapon.Range)
                {
                    if (!weapon.isAttacking)
                    {
                        weapon.doAttack(character);
                    }
                }
                else
                {
                    needsToMove = true;
                }
            }
            dir = targetVector.normalized;
            // if not all weapons in range move to character until all weapons are in range
            if (needsToMove)
            {
                rigidbody2D.velocity = dir * MovementSpeed;
            }

            yield return new WaitForFixedUpdate();
        }

        // if we killed the other character, we level up!
        if (character.isDead)
        {
            Debug.Log("I become stronger!");
            for (int i = 0; i < 5; ++i ){
                addRandomGlyph();
            }
            StartGlyphcount += 5;
            applySizeToGlyphCount(StartGlyphcount);
            ownCharacter.resetHitPoints();
        }
    }

    void addRandomGlyph()
    {
        DamageType type = DamageType.Fire;
        switch (Random.Range(1, 5))
        {
            case 1:
                type = DamageType.Fire;
                break;
            case 2:
                type = DamageType.Earth;
                break;
            case 3:
                type = DamageType.Water;
                break;
            case 4:
                type = DamageType.Wind;
                break;
        }
        ownCharacter.addGlyphToStack(type);

        int randomSlot = Random.Range(1, 4);
        switch (randomSlot)
        {
            case 1:
                incWeaponLevels(type, 1.0f);
                break;
            case 2:
                switch (type)
                {
                    case DamageType.Fire: ownCharacter.FireDefence += 1; break;
                    case DamageType.Earth: ownCharacter.EarthDefence += 1; break;
                    case DamageType.Water: ownCharacter.WaterDefence += 1; break;
                    case DamageType.Wind: ownCharacter.WindDefence += 1; break;
                }
                break;
            case 3:
                MovementSpeed = Mathf.Min(MaxSpeed, MovementSpeed + 1.0f / 10.0f);
                break;
        }
    }

    void incWeaponLevels(DamageType type, float amount)
    {
        foreach (Weapon weapon in weapons)
        {
            weapon.incDamage(type, amount);
        }
    }

    public void applySizeToGlyphCount(int glyphCount)
    {
        float size = Mathf.Min(2.0f, 1.0f + glyphCount / 20.0f);
        transform.localScale = new Vector3(size, size, size);
        ownCharacter.Scale = size;
    }

    void stopAllAttacks()
    {
        foreach (Weapon weapon in weapons)
        {
            weapon.stopAttack();
        }
    }
}
