using UnityEngine;
using System.Collections;
using Framework.Entities;
using Framework.StatSystem;
using Framework.Debugging;
using Framework.Utility;
using Framework.Extensions;

public class WatcherLogic : CoreBehaviour
{
    public float sightRange = 10f;
    public float fieldOfView = 100f;
    public Light eyeLight; 
    public GameObject target = null;
    public AudioClip foundClip;
    private UnityTimer attentionTimer = new UnityTimer(2f, false);
    private UnityTimer attackTimer = new UnityTimer(1f, false);
    private ActorClassifier actorClassifier;
    private bool addMark = true;
    private bool removeMark = false;


    protected override void InnerAwake()
    {
        this.actorClassifier = GetComponent<ActorClassifier>();
    }

    protected override void InnerUpdate()
    {
        // In range
        if (target != null)
        {
            Interact(new WanderingBehaviour.StopAutoMoveAction());
            if(CanSee(this.target))
            {
                if(addMark)
                {
                    this.target.Interact(new AlchemistDestroyAbility.AddMarkAction());
                    this.addMark = false;
                    this.removeMark = true;
                }
                Interact(new TurnAction(target.transform.position));
                this.attentionTimer.Reset();
                this.attackTimer.Advance();

                if (this.attackTimer.IsComplete())
                {
                    Interact(new WatcherAttack.AttackAction(target.transform.position));
                    this.attackTimer.Reset();
                }

                if (Vector3.Distance(this.transform.position, this.target.transform.position) > 5f)
                {
                    Interact(new MoveAction(target.transform.position));
                }
                else if (Vector3.Distance(this.transform.position, this.target.transform.position) < 4.5f)
                {
                    Interact(new MoveAction(this.transform.position + (this.transform.position - this.target.transform.position).normalized));
                }
                else
                {
                    Interact(new StopAction());
                }
            }
            else
            {
                if (removeMark)
                {
                    this.target.Interact(new AlchemistDestroyAbility.RemoveMarkAction());
                    this.addMark = true;
                    this.removeMark = false;
                }
                Interact(new StopAction());
                this.attentionTimer.Advance();
                if (this.attentionTimer.IsComplete())
                {
                    this.target = null;
                }
            }
        }
        else
        {
            Interact(new WanderingBehaviour.StartAutoMoveAction());

            Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, this.sightRange);
            for (int i = 0; i < hitColliders.Length; i++)
            { 
                GameObject found = hitColliders[i].gameObject;
                if (CanSee(found))
                {
                    this.target = found;
                    //AudioSource.PlayClipAtPoint(foundClip, this.transform.position);
                }
            }
        }

        if (Vector3.Distance(Camera.main.transform.position, this.transform.position) > 30f && eyeLight.enabled == true)
        {
            eyeLight.enabled = false;
        }
        else if(Vector3.Distance(Camera.main.transform.position, this.transform.position) <= 30f && eyeLight.enabled == false)
        {
            eyeLight.enabled = true;
        }

        //AvoidAllies();
    }

    private void AvoidAllies()
    {
        Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, this.sightRange);
        for (int i = 0; i < hitColliders.Length; i++)
        {
            GameObject subject = hitColliders[i].gameObject;
            ActorClassifier subjectActorClassifier = subject.GetComponent<ActorClassifier>();
            if (subjectActorClassifier != null && subjectActorClassifier.team == this.actorClassifier.team)
            {
                if (Vector3.Distance(this.transform.position, subject.transform.position) < 1f)
                {
                    Interact(new MoveAction(this.transform.position + (this.transform.position - subject.transform.position).normalized));
                }
            }
        }
    }

    private bool CanSee(GameObject subject)
    {
        ActorClassifier subjectActorClassifier = subject.GetComponent<ActorClassifier>();
        if (subjectActorClassifier != null 
            && subjectActorClassifier.team != this.actorClassifier.team
            && subjectActorClassifier.stealth > 0.6f)
        {
            Vector3 subjectDirection = (subject.transform.position - this.transform.position).normalized;
            // In field of view
            if (Vector3.Angle(this.transform.forward, subjectDirection) < (fieldOfView / 2f)
                && Vector3.Distance(this.transform.position, subject.transform.position) < this.sightRange)
            {
                Vector3 lookPosition = this.transform.position;
                //RaycastHit hit;
                //if (Physics.Raycast(this.transform.position, Vector3.down, out hit, 100, 1 << LayerMask.NameToLayer("Ground")))
                //{
                //    lookPosition = hit.point + (Vector3.up * 0.5f);
                //}
                // There's no obstacles!
                RaycastHit hit2;
                if (!Physics.Raycast(lookPosition, subjectDirection, out hit2, Vector3.Distance(lookPosition, subject.transform.position) - 1f, 1 << LayerMask.NameToLayer("Scene")))
                {
                    Draw.Line(lookPosition, subject.transform.position, Color.magenta);
                    return true;
                }
            }
        }
        return false;
    }
}
