using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace GhostArena5
{
    public enum EntityType
    {
        Player,
        Ghost
    }

    public enum EntityState
    {
        Alive,
        Dying,
        Dead
    }

   public enum Direction
    {
        North,
        NorthEast,
        East,
        SouthEast,
        South,
        SouthWest,
        West,
        NorthWest
    }
   
    public class Entity
    {
        private static Vector2 vecMin, vecMax;

        private EntityType _type;

        private EntityState _state;

        private int _health;

        private Vector2 _location;

        private Direction _moveDirection;
        private Direction _shootDirection;

        private float _speed;

        private int _curFrame;
        private int _numFrames;
        private float _animationDelay;

        private float _frameUpdate;

        private int _textureWidth;

        private BulletManager _bulletManager;
                
        public EntityType Type
        {
            get { return _type; }
        }

        public EntityState State
        {
            get { return _state; }
        }

        public Vector2 Location
        {
            get { return _location; }
        }

        public Direction MoveDirection
        {
            get { return _moveDirection; }
            set { _moveDirection = value; }
        }

        public Direction ShootDirection
        {
            get { return _shootDirection; }
            set { _shootDirection = value; }
        }

        public float Speed
        {
            get { return _speed; }
            set { _speed = value; }
        }

        public int CurFrame
        {
            get { return _curFrame; }
            set { _curFrame = value; }
        }

        public int NumFrames
        {
            get { return _numFrames; }
            set { _numFrames = value; }
        }

        public int Health
        {
            get { return _health; }
        }

        public Entity(EntityType type, Vector2 location, Direction orientation, int numFrames, int textureWidth, Game game)
        {
            _shootDirection = orientation;
            _type = type;
            _location = location;
            _numFrames = numFrames;
            _curFrame = 0;
            _textureWidth = textureWidth;

            _frameUpdate = 0.0f;

            switch (type)
            {
                case EntityType.Ghost:
                    _health = ((Game1)game).Difficulty.GhostHealth;
                    break;

                case EntityType.Player:
                    _health = 100;
                    break;
            }

            _bulletManager = new BulletManager(game);

            //account for the walls of the level (20) and half the sprite size (32)
            vecMin = new Vector2(20+32, 88+32);
            vecMax = new Vector2(game.Window.ClientBounds.Width - 20 - 32, game.Window.ClientBounds.Height - 20 - 32);

            //ghosts start off moving
            if (_type == EntityType.Ghost)
                _speed = ((Game1)game).Difficulty.GhostSpeed;
        }

        public int CurFrameX
        {
            get { return _curFrame * (_textureWidth / _numFrames); }
        }

        public int FrameWidth
        {
            get {return _textureWidth / _numFrames;}
        }

        public void Update(GameTime gameTime, Vector2 playerLocation)
        {
            //if ghost, change move direction if necessary based on player location
            if (_type == EntityType.Ghost)
            {
                //figure out if our current direction is greater than 45 degrees to the player. If so, we need to turn
                _moveDirection = GetDirectionFromVectors(_location, playerLocation);
                _shootDirection = _moveDirection;
            }

            if (_speed > 0.0f)
            {
                switch (_moveDirection)
                {

                    case Direction.East:
                        _location.X += _speed;

                        break;

                    case Direction.North:

                        _location.Y -= _speed;

                        break;

                    case Direction.NorthEast:

                        _location.Y -= _speed;
                        _location.X += _speed;

                        break;

                    case Direction.NorthWest:

                        _location.Y -= _speed;
                        _location.X -= _speed;

                        break;

                    case Direction.South:

                        _location.Y += _speed;
                        break;

                    case Direction.SouthEast:

                        _location.Y += _speed;
                        _location.X += _speed;
                        break;

                    case Direction.SouthWest:

                        _location.Y += _speed;
                        _location.X -= _speed;
                        break;

                    case Direction.West:

                        _location.X -= _speed;
                        break;
                }

                _location = Vector2.Clamp(_location, vecMin, vecMax);
            }

            _bulletManager.Update();

            if (_type == EntityType.Ghost)
            {
                _frameUpdate += gameTime.ElapsedGameTime.Milliseconds;

                if (_frameUpdate >= 500.0f)
                {
                    //increment frame
                    _curFrame++;

                    if (_curFrame > _numFrames - 1)
                        _curFrame = 0;

                    _frameUpdate -= 500.0f;
                }
            }
        }

        public bool SpawnBullet()
        {
            return _bulletManager.Spawn(this.ShootDirection, this.Location);
        }

        public void DrawBullets(SpriteBatch sb)
        {
            _bulletManager.Draw(sb);
        }

        public bool CheckBulletCollision(Entity entity)
        {
            if (_bulletManager.CheckCollision(entity))
                return true;

            return false;
        }

        public void Dispose()
        {
            _bulletManager.Clear();
        }

        public void DrainLife(int amount)
        {
            _health -= amount;
            if (_health <= 0)
                _state = EntityState.Dead;
        }

        public static Direction GetDirectionFromVectors(Vector2 vecFrom, Vector2 vecTo)
        {
            float x = vecTo.X - vecFrom.X;
            float y = vecTo.Y - vecFrom.Y;

            float angle = (float)(Math.Atan2(y, x) * 57.2957795);
            Direction dir;

            if (angle < 0)
            {
                if (angle > -23)
                    dir = Direction.East;
                else if (angle >= -67)
                    dir = Direction.NorthEast;
                else if (angle >= -112)
                    dir = Direction.North;
                else if (angle >= -157)
                    dir = Direction.NorthWest;
                else
                    dir = Direction.West;
            }
            else
            {
                if (angle < 23)
                    dir = Direction.East;
                else if (angle <= 67)
                    dir = Direction.SouthEast;
                else if (angle <= 112)
                    dir = Direction.South;
                else if (angle <= 157)
                    dir = Direction.SouthWest;
                else
                    dir = Direction.West;
            }

            return dir;
        }
    }
}
