using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Ika.Graphics;
using TestBoids.Collisions;


namespace TestBoids.Entities
{
    public class Boid : Entity
    {
        public int Level = 1;
        private bool m_isAlive = true;
        public bool isAlive
        {
            get { return m_isAlive; }
            set {
                if (m_isAlive)
                {
                    m_isAlive = value;
                    Speed = new Vector2(0, 4.5f);
                    if(Leader) Leader = false;
                }
            }
        }

        private bool m_isLeader;
        public bool Leader
        {
            get { return m_isLeader; }
            set
            {
                if (value != m_isLeader)
                {
                    m_isLeader = value;
                    if (value)
                        ((CircleCollision)Collision).Radius *= 2;
                    else
                        ((CircleCollision)Collision).Radius /= 2;
                }
            }
        }

        float m_mass = 1f;
        float m_acceleration = 6f;

        float m_passiveTimerMax = 3f;
        float m_passiveTimer = 0f;

        public bool m_isPassive = true;

        public Boid m_leader;

        Vector2 m_goal;

        public List<Entity> m_near = new List<Entity>();

        public Boid (Vector2 position, Sprite sprite, float maxSpeed)
            : base(position, sprite, maxSpeed)
        {
            MovementType = EntityMovementType.MT_Dynamic;
        }

        public void SetGoal(Vector2 absoluteGoal)
        {
            m_goal = absoluteGoal;
        }

        public void UpdateSpeed(float dt)
        {
            Vector2 relativeGoal = m_goal - m_position;
            if (relativeGoal.Length() > 0)
            {
                relativeGoal.Normalize();
            }

            m_speed.Y += relativeGoal.Y * m_acceleration / m_mass * dt;
            m_speed *= 0.90f;

            if (relativeGoal.X > 0)
            {
                m_speed.X = m_maxSpeed;
            }
            
        }

        public bool IsInFOV(Boid s, Entity other, float angle)
        {
            Vector2 distance = other.Position - s.Position;
            float realAngle = (float)Math.Atan2(distance.Y, distance.X);
            if (Math.Abs(realAngle) < angle / 2)
            {
                return true;
            }
            return false;
        }

        void UpdatePassivestate(float dt)
        {
            /* Le boid est il passif */
            if (Leader || m_leader != null)
            {
                m_isPassive = false;
                m_passiveTimer = m_passiveTimerMax;
            }
            else
            {
                if (m_passiveTimer > 0)
                {
                    m_passiveTimer -= dt;
                }
                else
                {
                    m_passiveTimer = 0;
                  //  m_isPassive = true;
                }
            }
        }

        void DesactivateNearLeaders()
        {
            if (Leader)
            {
                float m_maxDistance = 10;
                /* Desactive les leader trop pres d'un d'autres leaders */
                IList<Entity> near = m_sceneManager.FindInRadius(Position, m_maxDistance);
                foreach (Entity o in near)
                {
                    if (o != this && o is Boid && ((Boid)o).Leader)
                    {
                        ((Boid)o).Leader = false;
                    }
                }
            }
        }

        void UpdateMaxSpeed()
        {
            /* Ajuste la vitesse en fonction des voisins */
            MaxSpeed = 8;
            if (Leader)
            {
                MaxSpeed = 6;
            }
            else if (m_near.Count == 0)
            {
                MaxSpeed = 6f;
            }
            else if (m_near.Count > 2)
            {
                if (m_leader != null)
                {
                    MaxSpeed = 6.4f;
                }
                else
                {
                    MaxSpeed = 5.8f;
                }
            }

            if (m_leader != null && !Leader)
            {
                if (m_leader.Position.X < Position.X)
                {
                    MaxSpeed *= 0.4f;
                }
                if (!m_near.Contains(m_leader))
                {
                    MaxSpeed *= 0.8f;
                }
            }

            MaxSpeed = (m_passiveTimerMax - m_passiveTimer) / m_passiveTimerMax * 2.0f + (m_passiveTimer) / m_passiveTimerMax * MaxSpeed;
        }

        void SyncWithCam(float desiredX)
        {           
            /* Rattrape ou attends la camera */
            float x = Scene.ScreenToWorld(new Vector2(desiredX, 0)).X;
            if (Leader)
            {
                if (Position.X < x)
                {
                    MaxSpeed *= 1.4f;
                }
                else if (Position.X > x)
                {
                    MaxSpeed *= 0.6f;
                }
            }
        }

        public override void Update(float dt)
        {
            if (Collision != null)
                Collision.UpdatePosition(Position);

            if (isAlive)
            {

                DesactivateNearLeaders();

                UpdatePassivestate(dt);

                UpdateMaxSpeed();

                SyncWithCam(250);

                UpdateSpeed(dt);
            }
            
        }
    }
}
