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

using HamJam.AI;
using HamJam.Character;

public class AIManagerScript : MonoBehaviour {

    private List<MobData> _trackedHeros = new List<MobData>();
    private MobData _raidBoss;
    private AttackDataManagerScript _attackDataManager;

    void Awake() {
        // Get a reference to the raid boss
        this._raidBoss = new MobData(GameObject.FindGameObjectWithTag("RaidBoss"));
        // Get references to all existing heros
        foreach (var hero in GameObject.FindGameObjectsWithTag("Hero")) {
            this.TrackNewHero(hero);
        }
        this._attackDataManager = GameObject.FindGameObjectWithTag("AttackDataManager").GetComponent<AttackDataManagerScript>();
    }

    void Update() {
        MobData toRemove = null;
        foreach (var hero in this._trackedHeros) {
            if (!hero.CharInteracScript.IsAlive) {
                toRemove = hero;
                break;
            }
            // Choose what to do
            AttackTypes chosenAttack;
            MobData chosenTarget;
            this.GetHeroDecision(hero, out chosenAttack, out chosenTarget);
            if (chosenAttack == AttackTypes.None || chosenTarget == null) {
                Debug.LogWarning("Nothing was returned!");
                continue;
            }
            // Make it so.
            float attackRange = this._attackDataManager.GetAttackRange(chosenAttack);
            Vector2 directionToTarget = chosenTarget.RBody.position - hero.RBody.position;
            float distanceToTarget = directionToTarget.magnitude;
            // Normalize direction to target
            directionToTarget.Normalize();
            if (distanceToTarget <= attackRange) {
                // Within attack range, so attack
                hero.CharInteracScript.PerformAttack(directionToTarget, chosenAttack);
            } else {
                // Move towards it, with a bit of randomization
                // Check if the prefab has a defined randomization
                if (0 <= hero.CharInteracScript.MovementRandomizationScalar) {
                    // One was defined
                    directionToTarget.x += Random.value * hero.CharInteracScript.MovementRandomizationScalar;
                    directionToTarget.y += Random.value * hero.CharInteracScript.MovementRandomizationScalar;
                } else {
                    directionToTarget.x += Random.value * 0.3f;
                    directionToTarget.y += Random.value * 0.3f;
                    hero.CharInteracScript.Move(directionToTarget);
                }
            }
        }
        if (null != toRemove) {
            this._trackedHeros.Remove(toRemove);
        }
    }

    private void GetHeroDecision(MobData hero, out AttackTypes chosenAttackOut, out MobData chosenTarget) {
        AttackTypes bestAttackOption = AttackTypes.None;
        MobData bestTarget = null;
        float heuristic = 0;

        if (hero.CharInteracScript.AttackList.Contains(AttackTypes.WizardHealingBolt)) {
            // Consider healing allies
            foreach (var otherHero in this._trackedHeros) {
                if (otherHero == hero) {
                    continue;
                }
                float newHeuristic = (1f - otherHero.CharInteracScript.PercentageHealth) + (Random.value * 0.3f);
                if (newHeuristic > heuristic) {
                    bestTarget = otherHero;
                    bestAttackOption = AttackTypes.WizardHealingBolt;
                    heuristic = newHeuristic;
                }
            }
        }
        if (hero.CharInteracScript.AttackList.Contains(AttackTypes.WizardFireBall)) {
            float newHeuristic = Random.value + 0.0001f;
            if (newHeuristic > heuristic) {
                bestTarget = this._raidBoss;
                bestAttackOption = AttackTypes.WizardFireBall;
                heuristic = newHeuristic;
            }
        }
        if (hero.CharInteracScript.AttackList.Contains(AttackTypes.WarriorSwing)) {
            float newHeuristic = Random.value + 0.0001f;
            if (newHeuristic > heuristic) {
                bestTarget = this._raidBoss;
                bestAttackOption = AttackTypes.WarriorSwing;
                heuristic = newHeuristic;
            }
        }
        if (hero.CharInteracScript.AttackList.Contains(AttackTypes.ArrowToTheKnee)) {
            float newHeuristic = Random.value + 0.5f;
            if (newHeuristic > heuristic) {
                bestTarget = this._raidBoss;
                bestAttackOption = AttackTypes.ArrowToTheKnee;
                heuristic = newHeuristic;
            }
        }
        
        chosenAttackOut = bestAttackOption;
        chosenTarget = bestTarget;
    }


    public void TrackNewHero(GameObject newChar) {
        this._trackedHeros.Add(new MobData(newChar));
    }

}
