using UnityEngine;
using System.Collections;
using Framework.Entities;
using Framework.Extensions;
using System.Linq;
using System.Collections.Generic;
using Framework.InteractionSystem;
using Framework.Utility;
using Framework.Debugging;
using Project.Sound;

namespace Project.Actors
{
    public class BasicEnemySensor : CoreBehaviour
    {
        public class ExposeTargetAction : CoreAction
        {
            public ActorClassifier target;

            public ExposeTargetAction(ActorClassifier target)
            {
                this.target = target;
            }
        }

        public class ClearTargetAction : CoreAction {}

        public float viewRange = 6f;
        public AudioClip alertClip;
        private List<ActorClassifier> targets;
        private UnityTimer lookTimer;
        private UnityTimer forgetTimer;
        private ActorClassifier actorClassifier; 

        // Use this for initialization
        protected override void InnerAwake()
        {
            this.lookTimer = new UnityTimer(0.01f, false);
            this.targets = new List<ActorClassifier>();
            this.actorClassifier = GetComponent<ActorClassifier>();
            this.forgetTimer = new UnityTimer(2f, false);
        }

        // Update is called once per frame
        protected override void InnerUpdate()
        {
            UpdateTargets();

            if (this.targets.Count > 0)
            {
                Interact(new ExposeTargetAction(this.targets[0]));
                this.forgetTimer.Reset();
            }
            else
            {
                this.forgetTimer.Advance();
                if (this.forgetTimer.IsComplete())
                {
                    //Debug.Log("Forgot target.");
                    Interact(new ClearTargetAction());
                    this.forgetTimer.Reset();
                }
            }
        }

        private void UpdateTargets()
        {
            this.lookTimer.Advance();
            if (this.lookTimer.IsComplete())
            {
                List<ActorClassifier> newTargets = new List<ActorClassifier>();

                ActorClassifier[] actors = GameObject.FindObjectsOfType<ActorClassifier>();
                actors = actors
                    .Where(i => Vector3.Distance(this.transform.position, i.transform.position) < this.viewRange)
                    .Where(i => i.teamNumber != this.actorClassifier.teamNumber).ToArray();


                RaycastHit hit;
                for (int i = 0; i < actors.Length; i++)
                {
                    Vector3 eyePoint = this.transform.position + (Vector3.up * 0.5f);
                    Vector3 lookDirection = actors[i].transform.position + (Vector3.up * 0.5f) - eyePoint;
                    //Draw.Line(eyePoint, eyePoint + lookDirection, Color.red);
                    if (!Physics.Raycast(eyePoint, lookDirection, out hit, Vector3.Distance(eyePoint, actors[i].transform.position + (Vector3.up * 0.5f)) - 0.5f, 1 << 9))
                    {
                        Draw.Line(eyePoint, eyePoint + lookDirection, Color.green);
                        newTargets.Add(actors[i]);
                        if (!this.targets.Contains(actors[i]) || Random.RandomRange(0f,1f) < 0.003f)
                        {
                            Announce(new AudioVisualDirector.SoundAction(this.alertClip, this.transform.position, 2f));
                        } 
                    }
                }
                this.targets.Clear();
                this.targets.AddRange(newTargets);

                this.lookTimer.Reset();
            }
        }
    }
}