using KellysMarvelousAdventure.Utilities;
using Otter;
using System;

namespace KellysMarvelousAdventure.entities
{
    class BlueCat : Entity
    {
        private Spritemap<string> _spriteMap;
        private bool isSeekingTarget = true;
        private float closestDistanceItem = 3650f;
        private Entity closestItem;
        private double angleInRadians = 1;//this is about 57 degrees. ;-)
        private bool isHittingTarget = false;
        private int scanAgain = 100;
        private float troopX = 0;
        private float troopY = 0;
        private int firstTimer = 10;
        private int hitTimerMax = Rand.Int(100, 150);
        private int hitTimer;
        private Collider cat;//if needed
        private bool one = true;

        public int EnemyTroopHealth = 10;//hmmm half of the current coins + 10?

        public BlueCat(float x, float y)
        {
            X = x; Y = y;
            X = x; Y = y;
            SetHitbox(20, 20, (int)Global.Type.BLUECAT);
            Collider.X = -7;
            Collider.Y = -7;
            _spriteMap = new Spritemap<string>(Assets.BLUECAT, 46, 50);
            _spriteMap.Add("standRight", new int[] { 5 }, new float[] { 5f, 5f });
            _spriteMap.Add("standLeft", new int[] { 0 }, new float[] { 5f, 5f });
            _spriteMap.Add("walkRight", new int[] { 5, 6 }, new float[] { 5f, 5f });
            _spriteMap.Add("walkLeft", new int[] { 0, 1 }, new float[] { 5f, 5f });
            _spriteMap.Add("shootRight", new int[] { 8, 9 }, new float[] { 7f, 7f });
            _spriteMap.Add("shootLeft", new int[] { 3, 4 }, new float[] { 7f, 7f });
            _spriteMap.Add("death", new int[] { 1, 2, 3, 0, 1, 2, 1, 3, 5, 2, 7, 8 }, new float[] { 3f, 3f });
            _spriteMap.Play("standLeft");
            //_spriteMap.Color = Color.Random;
            _spriteMap.CenterOrigin();
            Graphic = _spriteMap;
            hitTimer = hitTimerMax;
            Layer = 1;
            //angleInRadians = GetAngle(Rand.Float(0f, 359f));
        }

        public override void Update()
        {
            base.Update();
            troopX = X; troopY = Y;
            //Console.WriteLine("currentAnim: {0}", _spriteMap.CurrentAnim);
            //Console.WriteLine("currentFrame: {0}", _spriteMap.CurrentFrame);
            //Console.WriteLine("currentFrameIndex: {0}", _spriteMap.CurrentFrameIndex);
            if (_spriteMap.CurrentAnim == "death") //if you are dying, do it. don't do anything else!
            {
                if (_spriteMap.CurrentFrameIndex == 11)
                {
                    RemoveSelf();
                    Global.kills++;
                    Global.score+=5;
                }
            }
            else
            {
                if (isSeekingTarget)
                {
                    ScanAllTargets();
                }
                else if (AmICollidingWithMyFriends())//if colliding with myself, move away.
                {
                    if (!AmICollidingWithWalls())
                    {
                        var speed = .5f;
                        X -= speed * (float)Math.Cos(angleInRadians);
                        Y -= speed * (float)Math.Sin(angleInRadians);
                        ChangeAnimTo("walkRight");
                        one = true;
                    }
                }
                else if (!AmCloseEnoughToAnythingToShootIt())//travel to target
                {
                    X -= Global.catSpeed * (float)Math.Cos(angleInRadians);
                    Y -= Global.catSpeed * (float)Math.Sin(angleInRadians);
                    ChangeAnimTo("walkLeft");
                    one = true;
                }
                else if (isHittingTarget)
                {
                    if (one || hitTimer <= 0)
                    {
                        hitTimer = hitTimerMax;
                        one = false;
                        Scene.Add(new Bullet(X, Y, closestItem));
                        PlayWurgely();
                    }
                    ChangeAnimTo("shootRight");
                    hitTimer--;
                }
                if (scanAgain <= 0)
                {
                    isSeekingTarget = true;
                    closestItem = null;
                    closestDistanceItem = 1670;
                    scanAgain = 100;
                }
                if (scanAgain > 0)
                    scanAgain--;
                //collide with yourself technology
                if (firstTimer > 0)
                    firstTimer--;
                if (firstTimer <= 0)
                {
                    if (cat != null)//you are still colliding with another. get a new angle.
                    {
                        angleInRadians = GetAngle(Rand.Float(0f, 359f));
                        firstTimer = 100;
                    }
                }

                var deflectedBullet = Collider.Collide((int)X, (int)Y, (int)Global.Type.DEFLECTEDBULLET);
                if (deflectedBullet != null)
                {
                    Bullet b = (Bullet)deflectedBullet.Entity;
                    b.Destroy();
                    ChangeAnimTo("death");
                    SoundManager.PlayRequestedSound("_catDeath");
                }
                var se = Collider.Collide((int)X, (int)Y, (int)Global.Type.SAPPEXPLOSION);
                if (se != null)
                {
                    ChangeAnimTo("death");
                    SoundManager.PlayRequestedSound("_catDeath");
                }
            }
        }//end update

        private void PlayWurgely()
        {
            var rand = Rand.Int(1, 5);//one more that what you want...
            if (rand == 1)
                SoundManager.PlayRequestedSound("_wurgely");
            else if (rand == 2)
                SoundManager.PlayRequestedSound("_wurgely2");
            else if (rand == 3)
                SoundManager.PlayRequestedSound("_wurgely3");
            else
                SoundManager.PlayRequestedSound("_wurgely4");
        }

        public void ScanAllTargets()
        {
            var anyPlayer = GetEntities<Player>();
            foreach (var item in anyPlayer)
            {
                var dist = Util.Distance(this, item);
                if (dist <= closestDistanceItem)
                {
                    closestDistanceItem = dist;
                    closestItem = item;
                }
            }
            if (closestItem != null)
            {
                isSeekingTarget = false;
                GetDirection();
            }
        }

        public void GetDirection()
        {
            var vector1 = new Point((int)closestItem.X, (int)closestItem.Y);
            var vector2 = new Point((int)X, (int)Y);
            angleInRadians = Math.Atan2(vector2.Y - vector1.Y, vector2.X - vector1.X);
            var angleInFrisbees = MathHelper.ToDegrees((float)angleInRadians);
            if (angleInFrisbees < 0)
            {
                angleInFrisbees += 360;
                angleInRadians = MathHelper.ToRadians(angleInFrisbees);
            }
        }

        public double GetAngle(float angle)
        {
            return MathHelper.ToRadians(angle);
        }

        public bool AmICollidingWithMyFriends()
        {
            cat = Collider.Collide(X, Y, (int)Global.Type.BLUECAT);
            if (cat != null)
                return true;
            else
                return false;
        }

        public bool AmICollidingWithWalls()
        {
            var wall = Collider.Collide(X, Y, (int)Global.Type.SOLID);
            if (wall != null)
                return true;
            else
                return false;
        }

        public bool AmCloseEnoughToAnythingToShootIt()
        {
            //get the distance to closest item. if close shoot at it!
            var dist = Util.Distance(this, closestItem);
            if (dist <= 200)
            {
                isHittingTarget = true;
                return true;
            }
            else
            {
                isHittingTarget = false;
                return false;
            }
        }

        public void ChangeAnimTo(string desiredAnimation)
        {
            if (_spriteMap.CurrentAnim != desiredAnimation)
                _spriteMap.Play(desiredAnimation);
        }

        public void Destroy()
        {
            if (_spriteMap.CurrentAnim != "death")
                _spriteMap.Play("death");
        }

        public override void Render()
        {
            base.Render();
            //Collider.Render(Color.Blue);
        }
    }
}
