using GiraffeRoller.Utility;
using Otter;
using System;

namespace GiraffeRoller.entities.enemies
{
    class WildGiraffe : Entity
    {
        private Spritemap<string> _spriteMap;
        private BasicMovement movement = new BasicMovement(1600, 1600, 1600);
        private bool isTimeToMove = true;
        private bool stand = false;
        private int rand = 0;
        private int walkTimer = 0;
        private int standTimer = 0;
        private bool _amIMovingLeft = false;
        private bool _amIMovingRight = false;
        private Button button = new Button();
        private float _forcedSpeed = .1f;//this is the decend rate to position. was 1
        //scanning!
        private float closestDistanceItem = 50f;//only if close do they come to you. it's a small space, i guess 100. (remember this setting is below too)
        private Entity closestItem;
        private double angleInRadians = 1;//this is about 57 degrees. ;-)
        private double reverseAngleInRadians = 1;
        private float angleInFrisbees = 1;
        private bool first = true;
        private Vector2 velocity = new Vector2(.3f, .3f);//this is the x and y speeds.
        private float _X;
        private float _Y;
        private bool one;
        private bool isInHall = false;

        private double speed = Rand.Float(2.0f, 6.0f);
        private float decayingnumber = 6;//initial force
        private double radianAngle = Rand.Float(.5f, 2.6f);
        private bool firstbounce = true;
        private bool secondbounce = false;
        private bool thirdbounce = false;
        private bool fourthbounce = false;
        private bool activateremove = false;
        private float triggerremove = 50;
        public bool donebouncing = false;
        public float BounceY = 12;
        private float _yo = 0;
        private bool isLeft = false;

        public int Health = 2;
        private float _scale;
        private bool isDead;

        public WildGiraffe(float x, float y)
        {
            X = x; Y = y;
            SetHitbox(50, 50, (int)Global.Type.WILDGIRAFFE);
            Collider.X = 25;
            Collider.Y = 25;
            _spriteMap = new Spritemap<string>(Assets.PLAYER, 100, 100);
            _spriteMap.Add("standRight", new int[] { 0 }, new float[] { 7f, 7f });//defaults to right
            _spriteMap.Add("standLeft", new int[] { 0 }, new float[] { 7f, 7f });//be sure to flip the spritemap before you use this.
            _spriteMap.Add("walkRight", new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, new float[] { 7f, 7f });
            _spriteMap.Add("walkLeft", new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, new float[] { 7f, 7f });//all left has to be flipped.
            _spriteMap.Add("stunned", new int[] { 2 }, new float[] { 5f, 5f });
            _spriteMap.Add("dying", new int[] { 10, 11 }, new float[] { 5f, 5f });
            _spriteMap.Add("dead", new int[] { 10 }, new float[] { 5f, 5f });
            _spriteMap.Play("standLeft");
            _spriteMap.Color = Color.Lerp(Color.White, Color.Black, Rand.Float(.1f, .7f));
            _scale = Rand.Float(.7f, 1.5f);//cool but need to scale collider with this. :/
            _spriteMap.Scale = _scale;
            _spriteMap.CenterOrigin();
            Graphic = _spriteMap;
            Layer = 1;

            //normal walk
            Axis axis = new Axis();
            movement.Axis = axis;
            movement.Axis.AddKeys(Key.P, Key.O, Key.I, Key.U);
            movement.Collider = Collider;
            movement.SpeedScale = 300;//normal speed
            movement.AddCollision((int)Global.Type.SOLID/*, (int)Global.Type.WILDGIRAFFE*/);
            movement.Axis.Locked = true;
            AddComponents(axis, movement, button);
            angleInRadians = GetAngle(Rand.Float(0f, 359f));
        }

        public override void Update()
        {
            base.Update();
            if (isDead)
            {
                Collider.RemoveTag(Global.Type.WILDGIRAFFE);
                if (X < 0)
                {
                    X += 5;
                    var angleInFrisbees = MathHelper.ToDegrees((float)radianAngle);
                    radianAngle = MathHelper.ToRadians(angleInFrisbees + 90);
                }
                else if (X >= Global.MW)
                {
                    X -= 5;
                    var angleInFrisbees = MathHelper.ToDegrees((float)radianAngle);
                    radianAngle = MathHelper.ToRadians(angleInFrisbees - 90);
                }
                else
                {
                    donebouncing = false;
                    var colls = Collider.Collide(X, Y, (int)Global.Type.SOLID);
                    if (colls != null)
                        X += 0;
                    if (isLeft)
                        X += (float)speed * (float)Math.Cos(radianAngle);
                    else
                        X -= (float)speed * (float)Math.Cos(radianAngle);
                    Y -= decayingnumber * (float)Math.Sin(radianAngle);
                    _spriteMap.Angle += 16;//was 6
                    decayingnumber -= .1f;
                    if (Y > BounceY + _yo && firstbounce)
                    {
                        firstbounce = false;
                        secondbounce = true;
                        decayingnumber = 4;//was 2
                        SoundManager.PlayRequestedSound(Shared.RandomFootstep());
                    }
                    else if (Y > BounceY + _yo && secondbounce)
                    {
                        decayingnumber = 2;
                        secondbounce = false;
                        thirdbounce = true;
                        SoundManager.PlayRequestedSound(Shared.RandomFootstep());
                    }
                    else if (Y > BounceY + _yo && thirdbounce)
                    {
                        decayingnumber = 1;
                        thirdbounce = false;
                        fourthbounce = true;
                        SoundManager.PlayRequestedSound(Shared.RandomFootstep());
                    }
                    else if (Y > BounceY + _yo && fourthbounce)
                    {
                        fourthbounce = false;
                        activateremove = true;
                        triggerremove = 30;
                        SoundManager.PlayRequestedSound(Shared.RandomFootstep());
                    }
                    if (activateremove)
                    {
                        Collider.AddTag(Global.Type.WILDGIRAFFE);
                        //SpringSprangSprung = false;
                        donebouncing = true;
                        _spriteMap.Angle = 0;
                        triggerremove -= .5f;
                        //reset variables no matter how many times you are hit and picked up.
                        speed = Rand.Float(2.0f, 6.0f);
                        decayingnumber = 6;//initial force
                        radianAngle = Rand.Float(.5f, 2.6f);
                        firstbounce = true;
                        secondbounce = false;
                        thirdbounce = false;
                        fourthbounce = false;
                        activateremove = false;
                        donebouncing = false;
                        _yo = 0;


                        var colld = Collider.Collide(X, Y, (int)Global.Type.SOLID);
                        if (colld != null || X < 0 || X >= Global.MW || Y < 0 || Y >= Global.MH)
                        {
                            X += 0;
                        }
                        Scene.Add(new DeadGiraffe(X, Y, _spriteMap.Color, _scale));
                        RemoveSelf();
                    }
                }
            }
            else
            {
                if (AmICollidingWithMyFriends(Collider) && first)
                {
                    movement.RemoveCollision((int)Global.Type.WILDGIRAFFE);//remove the collision so we can get away.
                    if (!movement.CollisionsSolid.Contains((int)Global.Type.RUNNINGWILDGIRAFFE))//if there is not collision dog, add it.
                        movement.AddCollision((int)Global.Type.RUNNINGWILDGIRAFFE);//walls
                    if (Timer % 34 == 0)
                        angleInRadians = GetAngle(Rand.Float(0f, 359f));
                    Global.wildGiraffeSpeed = .1f;
                    GetVelocity(angleInRadians);
                    movement.Axis.ForceState(velocity);
                }
                else
                {
                    movement.SpeedScale = 400;
                    movement.RemoveCollision((int)Global.Type.RUNNINGWILDGIRAFFE);
                    if (!movement.CollisionsSolid.Contains((int)Global.Type.WILDGIRAFFE))//if there is not collision dog, add it.
                        movement.AddCollision((int)Global.Type.WILDGIRAFFE);//walls
                    first = false;
                    if (isTimeToMove)
                    {//basic movement with interactions and states.
                        isTimeToMove = false;
                        walkTimer = Rand.Int(100, 150);
                        _forcedSpeed = Rand.Float(.005f, .03f);
                        rand = ScanAllTargets();
                    }
                    if (walkTimer > 0)
                    {
                        walkTimer--;
                        //Console.WriteLine("rand: {0} (1 up, 2 rightup, 3 right, 4 downright, 5 down, 6 downleft, 7 left, 8 upleft 9 yawn, 0 randomdirection", rand);
                        if (isInHall)
                            movement.Freeze = true;
                        else
                            movement.Freeze = false;
                        if (AmICollidingWithMyFriends(Collider))
                        {
                            movement.RemoveCollision((int)Global.Type.WILDGIRAFFE);//remove the collision so we can get away.
                            if (!movement.CollisionsSolid.Contains((int)Global.Type.RUNNINGWILDGIRAFFE))//if there is not collision dog, add it.
                                movement.AddCollision((int)Global.Type.RUNNINGWILDGIRAFFE);//walls
                            if (Timer % 34 == 0)
                                angleInRadians = GetAngle(Rand.Float(0f, 359f));
                            Global.wildGiraffeSpeed = .2f;
                            GetVelocity(angleInRadians);
                            movement.Axis.ForceState(velocity);
                        }
                        else
                        {
                            switch (rand)
                            {//why don't we just grab a random angle and try to walk in that direction?
                                case (int)Move.up:
                                    movement.Axis.ForceState(0, -_forcedSpeed);
                                    _amIMovingRight = true;
                                    _amIMovingLeft = false;
                                    break;
                                case (int)Move.upRight:
                                    movement.Axis.ForceState(_forcedSpeed, -_forcedSpeed);
                                    _amIMovingRight = true;
                                    _amIMovingLeft = false;
                                    break;
                                case (int)Move.right:
                                    movement.Axis.ForceState(_forcedSpeed, 0);
                                    _amIMovingRight = true;
                                    _amIMovingLeft = false;
                                    break;
                                case (int)Move.downRight:
                                    movement.Axis.ForceState(_forcedSpeed, _forcedSpeed);
                                    _amIMovingRight = true;
                                    _amIMovingLeft = false;
                                    break;
                                case (int)Move.down:
                                    movement.Axis.ForceState(0, _forcedSpeed);
                                    _amIMovingRight = false;
                                    _amIMovingLeft = true;
                                    break;
                                case (int)Move.downLeft:
                                    movement.Axis.ForceState(-_forcedSpeed, _forcedSpeed);
                                    _amIMovingRight = false;
                                    _amIMovingLeft = true;
                                    break;
                                case (int)Move.left:
                                    movement.Axis.ForceState(-_forcedSpeed, 0);
                                    _amIMovingRight = false;
                                    _amIMovingLeft = true;
                                    break;
                                case (int)Move.upLeft:
                                    movement.Axis.ForceState(-_forcedSpeed, -_forcedSpeed);
                                    _amIMovingRight = false;
                                    _amIMovingLeft = true;
                                    break;
                                case (int)Move.yawn:
                                    //Console.WriteLine("need to implement yawn?");
                                    if (one)
                                    {
                                        one = false;
                                        SoundManager.PlayRequestedSound(Shared.RandomFootstep(), .2f);
                                    }
                                    break;
                                default://or 0.
                                    Global.wildGiraffeSpeed = .1f;
                                    GetVelocity(angleInRadians);
                                    movement.Axis.ForceState(velocity);
                                    if (angleInFrisbees > 0 && angleInFrisbees <= 90 || angleInFrisbees > 270 && angleInFrisbees <= 360)
                                    {
                                        _amIMovingRight = true;
                                        _amIMovingLeft = false;
                                    }
                                    else
                                    {
                                        _amIMovingRight = false;
                                        _amIMovingLeft = true;
                                    }
                                    break;
                            }
                        }
                    }
                    if (!stand && walkTimer <= 0)
                    {
                        stand = true;
                        movement.Axis.ReleaseState();
                        movement.Freeze = true;
                        //Shared.ChangeAnimTo("standLeft", _spriteMap);
                        _spriteMap.FlippedX = true;
                        if (closestItem != null)
                            standTimer = Rand.Int(6, 60);
                        // Console.WriteLine("stand: {0}", stand);
                        //Console.WriteLine("stand timer: {0}", standTimer);
                    }
                    if (stand && standTimer > 0)
                    {
                        if (_amIMovingRight)
                        {
                            Shared.ChangeAnimTo("walkRight", _spriteMap);
                            _spriteMap.FlippedX = false;
                        }
                        else
                        {
                            Shared.ChangeAnimTo("walkLeft", _spriteMap);
                            _spriteMap.FlippedX = true;
                        }

                        standTimer--;
                    }
                    if (stand && standTimer <= 0)
                    {
                        //SoundManager.PlayRequestedSound(RandomYip(), .08f); MAYBE random statement
                        stand = false;
                        closestItem = null;
                        closestDistanceItem = 50f;
                        one = true;
                        isTimeToMove = true;
                    }
                    if (_amIMovingLeft && !stand)
                    {
                        Shared.ChangeAnimTo("walkLeft", _spriteMap);
                        _spriteMap.FlippedX = true;
                    }
                    if (_amIMovingRight && !stand)
                    {
                        Shared.ChangeAnimTo("walkRight", _spriteMap);
                        _spriteMap.FlippedX = false;
                    }
                    //map edges
                    var offset = 24;
                    if (X < -offset)
                        X = Global.MW - 9;
                    else if (X > Global.MW - 9)
                        X = -offset;
                    if (Y < -offset)
                        Y = Global.MH - 9;
                    else if (Y > Global.MH - 9)
                        Y = -offset;
                }
                var carts = Collider.Collide(X, Y, (int)Global.Type.BOSS);
                if (carts != null)
                {
                    Global.NumberOfGiraffesCollected++;
                    Global.Score--;
                    SoundManager.PlayRequestedSound(PlayRandomBossCollectedSound(), .8f);
                    SoundManager.PlayRequestedSound("_suckUp", .3f);
                    SoundManager.PlayRequestedSound("_giraffeDeathFast", .1f);//testing this might be too much too often too loud...
                    Destroy();
                }
            }
        }//end of update

        private string PlayRandomBossCollectedSound()
        {
            switch (Rand.Int(1, 2))//one more than the last case number (so counting the default would be an additional one)
            {
                case 1:
                    return "_scoot";
                default:
                    return "_softDoorClose";
            }
        }

        private string RandomDeathSound()
        {
            switch (Rand.Int(1, 11))//one more than the last case number (so counting the default would be an additional one)
            {
                case 1:
                    return "_death1";
                case 2:
                    return "_death2";
                case 3:
                    return "_death3";
                case 4:
                    return "_death4";
                case 5:
                    return "_death5";
                case 6:
                    return "_death6";
                case 7:
                    return "_death7";
                case 8:
                    return "_death8";
                case 9:
                    return "_death9";
                case 10:
                    return "_deathLoud";
                default:
                    return "_eh";
            }
        }

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

        private void GetVelocity(double originalAngle)//these speeds are not variable enough. :/
        {
            _X = Global.wildGiraffeSpeed * (float)Math.Cos(originalAngle);
            _Y = Global.wildGiraffeSpeed * (float)Math.Sin(originalAngle);
            velocity = new Vector2(_X, _Y);
        }

        public int ScanAllTargets()
        {
            var anyPlayer = GetEntities<Player>();
            foreach (var item in anyPlayer)
            {
                var dist = Util.Distance(this, item);
                if (dist <= closestDistanceItem)
                {
                    closestDistanceItem = dist;
                    closestItem = item;
                }
            }

            /*var anySniper = GetEntities<Agent>();
            foreach (var item in anySniper)
            {
                var dist = Util.Distance(this, item);
                if (dist <= closestDistanceItem)
                {
                    closestDistanceItem = dist;
                    closestItem = item;
                }
            }*/
            if (closestItem != null)
                return GetClosestDirection();
            else
                return GetRandomNumber();
        }

        public int GetClosestDirection()//this will return an angle to go there. or itshould have...
        {
            if (closestItem != null)
            {
                var vector2 = new Point((int)closestItem.X, (int)closestItem.Y);
                var vector1 = new Point((int)X, (int)Y);
                angleInRadians = Math.Atan2(vector2.Y - vector1.Y, vector2.X - vector1.X);
                angleInFrisbees = MathHelper.ToDegrees((float)angleInRadians);
                //var player = GetEntity<Player>();
                //var distX = player.X - X;
                //var distY = Math.Abs(player.Y - Y);
                if (angleInFrisbees < 0)
                {
                    angleInFrisbees += 360;
                    //Console.WriteLine("angle: {0}", angleInFrisbees);
                    angleInRadians = MathHelper.ToRadians(angleInFrisbees);
                }
                return 0;
            }
            else
                return GetRandomNumber();
        }

        public void GetDirection(int destX, int destY, int sourceX, int sourceY)
        {
            var vector1 = new Point(sourceX, sourceY);
            var vector2 = new Point(destX, destY);
            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 int GetRandomNumber()
        {
            //Console.WriteLine("getting a random number because no one is close enough. xD");
            angleInRadians = MathHelper.ToRadians(Rand.Angle);//grab a random angle!
            return Rand.Int(1, 10);
        }

        private enum Move
        {
            nothing,
            up,
            upRight,
            right,
            downRight,
            down,
            downLeft,
            left,
            upLeft,
            yawn
        }

        public double GetAngle(float angle)
        {
            var tempAngle = MathHelper.ToRadians(angle);
            reverseAngleInRadians = MathHelper.ToRadians(angle + 180);
            return tempAngle;
        }

        public void Destroy()
        {
            //SoundManager.PlayRequestedSound(RandomDeathSound(), .5f);
            if (!isDead)
            {
                isDead = true;
                Shared.ChangeAnimTo("dying", _spriteMap);
            }
        }

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



