using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using DataStructures;

namespace Sentience
{
    /// <summary>
    /// The entity class contains all the properties and methods for controlling entities.
    /// </summary>
    public class Entity : IName
    {
        public Entity(int id, Team team, Node<IBlock> node)
        {
            ID = id;
            CurrentNode = node;
            Position = CurrentNode.Location;
            Team = team;
            Size = Defaults.DefaultEntitySize;
            State = States.Idle;

            Waypoints = new List<Node<IBlock>>();
        }

        public Entity(int id, Team team)
        {
            ID = id;
            Team = team;
            Size = Defaults.DefaultEntitySize;
            State = States.Idle;

            Waypoints = new List<Node<IBlock>>();
        }

        public String Name { get { return String.Format("{0}[{1}]", Team.Behavior.Name, ID); }}

        /// <summary>
        /// The entity's unique identifier.
        /// </summary>
        public int ID { get; set; }

        /// <summary>
        /// The team it belongs to.
        /// </summary>
        public Team Team { get; set; }

        /// <summary>
        /// The current state.
        /// </summary>
        public States State { get; set; }

        /// <summary>
        /// The position of where to draw the entity.
        /// </summary>
        public PointF Position { get; set; }

        /// <summary>
        /// The entity's size.
        /// </summary>
        public Size Size { get; set; }

        /// <summary>
        /// The list of waypoints.
        /// </summary>
        public List<Node<IBlock>> Waypoints { get; set; }

        /// <summary>
        /// The current node that the entity is on (Waypoints[0]).
        /// </summary>
        public Node<IBlock> CurrentNode { get; set; }

        /// <summary>
        /// The target entity.
        /// </summary>
        public Entity Target { get; set; }

        /// <summary>
        /// The date and time the entity was spawned.
        /// </summary>
        public DateTime Spawn { get; set; }

        /// <summary>
        /// Perform the entity's team behavior.
        /// </summary>
        public void PerformBehavior()
        {
            Team.Behavior.Perform(this);
        }

        /// <summary>
        /// Get a string of where the entity is or if it has spawned.
        /// </summary>
        /// <returns>The location String.</returns>
        public String GetLocationLabel()
        {
            if (CurrentNode == null)
                return "[Not Spawned]";
            else
                return CurrentNode.ID.ToString();
        }

        /// <summary>
        /// Get a bool of whether the entity has spawned or not.
        /// </summary>
        /// <returns>If the entity has spawned.</returns>
        public bool HasSpawned()
        {
            if (CurrentNode == null)
                return false;
            else
                return true;
        }

        /// <summary>
        /// The Update function controls where the entity is and is going. It is a sub-loop of the main
        /// game loop.
        /// </summary>
        public void Update()
        {
            if (Waypoints.Count > 0)
            {
                bool AtDestination = false;

                if (Math.Abs(Position.X - Waypoints[0].Location.X) > 0.1f)
                    Position = new PointF(Position.X + (Waypoints[0].Location.X - Position.X) / (Defaults.MaxMovementSpeed - Properties.Settings.Default.MovementSpeed), Position.Y);
                else
                    AtDestination = true;

                if (Math.Abs(Position.Y - Waypoints[0].Location.Y) > 0.1f)
                {
                    Position = new PointF(Position.X, Position.Y + (Waypoints[0].Location.Y - Position.Y) / (Defaults.MaxMovementSpeed - Properties.Settings.Default.MovementSpeed));
                }
                else
                {
                    if (AtDestination)
                    {
                        CurrentNode = Waypoints[0];
                        Waypoints.RemoveAt(0);

                        // Perform the current block's actions.
                        CurrentNode.Data.Action(this);
                    }
                }
               
            }
            else
            {
                State = States.Idle;
                PerformBehavior();
            }

        }

        /// <summary>
        /// Draw the entity.
        /// </summary>
        /// <param name="graphics">The graphics object.</param>
        /// <param name="showData">Whether or not to show entity information.</param>
        /// <param name="showRadius">Whether or not to show the entity view distance.</param>
        public void Draw(Graphics graphics, bool showData, bool showRadius)
        {
            Update();

            if (showRadius)
                Drawing.Circle(graphics, Position, Team.ViewDistance, Team.Color, Color.FromArgb(25, Team.Color));

            Drawing.Box(graphics, Position, "", Size, Color.Black, Color.FromArgb(35, Team.Color));

            if (showData)
                Drawing.Text(graphics, ID + " - " + Team.Name + "\n" + State + " - " + CurrentNode.ID, Defaults.DefaultFont, Brushes.Blue, new PointF(Position.X + 10, Position.Y - 10));
        }
    }
}
