using Otter;
using PpbbffttMiningHa.entities.MapEntities;
using PpbbffttMiningHa.objects;
using PpbbffttMiningHa.scenes;
using PpbbffttMiningHa.Utility;

namespace PpbbffttMiningHa.entities
{
    class Player : Entity
    {
        #region Private Variables
        private Spritemap<string> _spriteMap;
        private BasicMovement movement = new BasicMovement(10000, 10000, 100);//init all the things.
        private BasicMovement fakemovement = new BasicMovement(10000, 10000, 20);//init all the things.
        private Axis _axis = new Axis();
        private readonly float xoffset = 10;
        public bool onedeath;
        private bool IsL;
        private bool IsR;
        private bool IsU;
        private bool IsD;
        private bool _hMove = true;
        private bool _vMove = true;
        private bool isTimeToActuallyDie = false;
        private int timeToDieTimer = 100;
        #endregion
        public static int IsJoystickAxisActive = 0;//use a Joystick axis instead of keys
        public static bool RefreshAxisButtons = false;

        public Player(float x, float y)
        {
            X = x; Y = y;
            SetHitbox(15, 35, (int)Global.Type.PLAYER);
            Collider.X = 20;//was 15
            Collider.Y = 25;//was 8 was 25
            #region SetCustomInputs
            movement.Axis = _axis;
            string tempUp = Global.PlayerSession.Data.GetString("P1Up");
            string tempRight = Global.PlayerSession.Data.GetString("P1Right");
            string tempDown = Global.PlayerSession.Data.GetString("P1Down");
            string tempLeft = Global.PlayerSession.Data.GetString("P1Left");
            if (tempRight.Contains("Joy"))
                movement.Axis = _axis.AddButton(Controllers.Controllers.TranslateInputKeysForInts(tempRight), Direction.Right, int.Parse(Global.PlayerSession.Data.GetString("P1JoystickNumber")));
            else if (tempRight.Contains("Key"))
                movement.Axis = _axis.AddKey((Key)Controllers.Controllers.TranslateInputKeysForInts(tempRight), Direction.Right);
            else if (tempRight.Contains("Mouse"))
                movement.Axis = _axis.AddMouseButton((MouseButton)Controllers.Controllers.TranslateInputKeysForInts(tempRight), Direction.Right);
            if (tempLeft.Contains("Joy"))
                movement.Axis = _axis.AddButton(Controllers.Controllers.TranslateInputKeysForInts(tempLeft), Direction.Left, int.Parse(Global.PlayerSession.Data.GetString("P1JoystickNumber")));
            else if (tempLeft.Contains("Key"))
                movement.Axis = _axis.AddKey((Key)Controllers.Controllers.TranslateInputKeysForInts(tempLeft), Direction.Left);
            else if (tempLeft.Contains("Mouse"))
                movement.Axis = _axis.AddMouseButton((MouseButton)Controllers.Controllers.TranslateInputKeysForInts(tempLeft), Direction.Left);
            if (tempDown.Contains("Joy"))
                movement.Axis = _axis.AddButton(Controllers.Controllers.TranslateInputKeysForInts(tempDown), Direction.Down, int.Parse(Global.PlayerSession.Data.GetString("P1JoystickNumber")));
            else if (tempDown.Contains("Key"))
                movement.Axis = _axis.AddKey((Key)Controllers.Controllers.TranslateInputKeysForInts(tempDown), Direction.Down);
            else if (tempDown.Contains("Mouse"))
                movement.Axis = _axis.AddMouseButton((MouseButton)Controllers.Controllers.TranslateInputKeysForInts(tempDown), Direction.Down);
            if (tempUp.Contains("Joy"))
                movement.Axis = _axis.AddButton(Controllers.Controllers.TranslateInputKeysForInts(tempUp), Direction.Up, int.Parse(Global.PlayerSession.Data.GetString("P1JoystickNumber")));
            else if (tempUp.Contains("Key"))
                movement.Axis = _axis.AddKey((Key)Controllers.Controllers.TranslateInputKeysForInts(tempUp), Direction.Up);
            else if (tempUp.Contains("Mouse"))
                movement.Axis = _axis.AddMouseButton((MouseButton)Controllers.Controllers.TranslateInputKeysForInts(tempUp), Direction.Up);
            #endregion
            Axis fakeAxis = Axis.CreateArrowKeys();
            fakemovement.Axis = fakeAxis;
            fakemovement.Axis.AddKeys(Key.P, Key.O, Key.I, Key.U);
            movement.AddCollision((int)Global.Type.SOLID, (int)Global.Type.BOTTOMROCK);//walls
            movement.Collider = Collider;
            fakemovement.AddCollision((int)Global.Type.SOLID, (int)Global.Type.BOTTOMROCK);
            fakemovement.Collider = Collider;
            //speed?
            movement.SpeedScale = 100;
            //create basic bubble movement settings
            AddComponents(_axis, movement, fakemovement);
            _spriteMap = new Spritemap<string>(Assets.PLAYER, 64, 64);
            AddNewSprites();
            ChangeAnimTo("standRight");
            Graphic = _spriteMap;
        }

        public override void UpdateFirst()//this is so that when the player moves the camera, the UI will update after it moves. (but the player will still appear below the elements. (it's an update thing)
        {
            base.UpdateFirst();
            #region Camera follows player
            if (X > Scene.HalfWidth - xoffset && X < Global.MW - Scene.HalfWidth - xoffset)//this is now universal. haha!
                Scene.CameraX = X - Scene.HalfWidth + xoffset;//this does follow the player!
            else if (X <= Scene.HalfWidth - xoffset)
                Scene.CameraX = 0;
            else if (X >= Global.MW - (Scene.HalfWidth * 2))
                Scene.CameraX = Global.MW - (Scene.HalfWidth * 2);
            if (Y > Scene.HalfHeight && Y < Global.MH - Scene.HalfHeight)
                Scene.CameraY = Y - Scene.HalfHeight;//this does follow the player!
            else if (Y <= Scene.HalfHeight)
                Scene.CameraY = 0;
            else if (Y >= Global.MH - Scene.HalfHeight * 2)
                Scene.CameraY = Global.MH - Scene.HalfHeight * 2;
            #endregion
        }

        public override void Update()
        {
            base.Update();
            //testing
            var cn = Global.PlayerSession.Controller;
            Global.PlayerX = X;
            Global.PlayerY = Y;
            Global.PlayerCurrentAnim = _spriteMap.CurrentAnim;
            //create artifical gravity to pull the player down?
            fakemovement.Axis.ForceState(0, 10f);
            #region Testing (r)
            if (cn.Button("P1Testing").Pressed)// this is for testing atm.
            {
                System.Console.WriteLine("MouseX: {0} MouseY: {1}", Scene.MouseX, Scene.MouseY);
                //Scene.Add(new LightningBottle(Scene.MouseX + 30, Scene.MouseY));
                //Global.Done = 0;
                //Global.CameraTimer = 3;
                //Global.IsScreenShake = true;
                Scene.Add(new FlyingDirt(Scene.MouseX, Scene.MouseY, Scene.MouseY + 12));
                Scene.Add(new FlyingDirt(Scene.MouseX, Scene.MouseY, Scene.MouseY + 12));
                Scene.Add(new FlyingDirt(Scene.MouseX, Scene.MouseY, Scene.MouseY + 12));
                Scene.Add(new FlyingDirt(Scene.MouseX, Scene.MouseY, Scene.MouseY + 12));
                Scene.Add(new FlyingDirt(Scene.MouseX, Scene.MouseY, Scene.MouseY + 12));
                Scene.Add(new FlyingDirt(Scene.MouseX, Scene.MouseY, Scene.MouseY + 12));
                Scene.Add(new Gem(Scene.MouseX, Scene.MouseY, Scene.MouseY + 12));
            }
            #endregion
            #region Testing (q)
            if (cn.Button("P1Testing2").Down)// this is for testing atm.
            {
                //Scene.Add(new SpecialItem(Scene.MouseX + 30, Scene.MouseY, "redBeads"));
            }
            #endregion
            //System.Console.WriteLine("currentAnim: {0}", _spriteMap.CurrentAnim);
            //System.Console.WriteLine("currentFrame: {0}", _spriteMap.CurrentFrame);
            //System.Console.WriteLine("currentFrameIndex: {0}", _spriteMap.CurrentFrameIndex);
            if (_spriteMap.CurrentAnim == "death" && _spriteMap.CurrentFrameIndex == 1)//so it's the same one... ???
            {
                isTimeToActuallyDie = true;
                timeToDieTimer = 100;
            }
            if (Global.PlayerHealth <= 0)
            {
                ChangeAnimTo("death");
                if (!onedeath)
                {
                    onedeath = true;
                    SoundManager.PlayRequestedSound("_ancientDeath");
                }
            }
            else
            {
                #region collisions
                if (cn.Button("P1Fire").Pressed)
                {
                    var floors = Collider.Collide(X, Y + 16, (int)Global.Type.SOLID);
                    if (floors != null)
                    {
                        ChangeAnimTo("fireGun");
                    }
                    else
                        ChangeAnimTo("flyFireGun");
                    Scene.Add(new Bomb(X + 50, Y + 50));

                }
                #endregion
                #region animations? set them?
                var floor = Collider.Collide(X, Y + 16, (int)Global.Type.SOLID);
                if (floor != null)
                    PressKeysForAnimation(cn, "walkLeft", "walkRight", "walkUp", "walkDown");
                else //we are flying, use the jetpack. simple as that...
                {
                    SoundManager.PlayRequestedSound("_jetPack", .3f);
                    PressKeysForAnimation(cn, "flyLeft", "flyRight", "flyUp", "flyDown");
                }
                #endregion
                #region Hmovement or Vmovement
                if (cn.Button("P1Left").Down)//LEFT
                    _hMove = true;
                else if (cn.Button("P1Right").Down)//RIGHT
                    _hMove = true;
                else
                    _hMove = false;
                if (cn.Button("P1Up").Down)//UP
                    _vMove = true;
                else if (cn.Button("P1Down").Down)//DOWN
                    _vMove = true;
                else
                    _vMove = false;
                #endregion
                StopWalkingAnimations();
                #region HandlingMapEdges
                //right and left
                //ok you check if it's safe to got there, if it is not place yourself exactly one pixel next to it.
                var offset = 15;//was 24
                if (X < -offset * 2)
                {
                    var colt = Collider.Collide((int)Global.MW - 15, (int)Y, Global.Type.SOLID);
                    if (colt != null)
                        X = -offset * 2;//same spot it's less than, not ==.
                    else
                        X = Global.MW - 15;
                }
                else if (X > Global.MW - 15)
                {
                    var colt = Collider.Collide((int)-offset * 2, (int)Y, Global.Type.SOLID);
                    if (colt != null)
                    {
                        X = Global.MW - 15;//same spot it's less than, not ==.
                    }
                    else
                        X = -offset * 2;
                }
                if (Y < -offset)
                    Y = 0;
                else if (Y > Global.MH)
                    Y = -offset;
                #endregion
            }
            #region Timers
            if (isTimeToActuallyDie)
            {
                System.Console.WriteLine("we are dying now, time to actually die is now true");
                ChangeAnimTo("dead");
                if (timeToDieTimer > 0)
                    timeToDieTimer--;
                if (timeToDieTimer <= 0)
                    Destroy();
            }
            #endregion
            #region refresh axis buttons check
            if (Global.IsPlayerOneAxisReset)
            {
                Global.IsPlayerOneAxisReset = false;

                string tempUp = Global.PlayerSession.Data.GetString("P1Up");
                string tempRight = Global.PlayerSession.Data.GetString("P1Right");
                string tempDown = Global.PlayerSession.Data.GetString("P1Down");
                string tempLeft = Global.PlayerSession.Data.GetString("P1Left");

                RemoveComponent(_axis);
                _axis = new Axis();
                movement.Axis = _axis;

                if (tempRight.Contains("Joy"))
                    movement.Axis = _axis.AddButton(Controllers.Controllers.TranslateInputKeysForInts(tempRight), Direction.Right, int.Parse(Global.PlayerSession.Data.GetString("P1JoystickNumber")));
                else if (tempRight.Contains("Key"))
                    movement.Axis = _axis.AddKey((Key)Controllers.Controllers.TranslateInputKeysForInts(tempRight), Direction.Right);
                else if (tempRight.Contains("Mouse"))
                    movement.Axis = _axis.AddMouseButton((MouseButton)Controllers.Controllers.TranslateInputKeysForInts(tempRight), Direction.Right);
                if (tempLeft.Contains("Joy"))
                    movement.Axis = _axis.AddButton(Controllers.Controllers.TranslateInputKeysForInts(tempLeft), Direction.Left, int.Parse(Global.PlayerSession.Data.GetString("P1JoystickNumber")));
                else if (tempLeft.Contains("Key"))
                    movement.Axis = _axis.AddKey((Key)Controllers.Controllers.TranslateInputKeysForInts(tempLeft), Direction.Left);
                else if (tempLeft.Contains("Mouse"))
                    movement.Axis = _axis.AddMouseButton((MouseButton)Controllers.Controllers.TranslateInputKeysForInts(tempLeft), Direction.Left);
                if (tempDown.Contains("Joy"))
                    movement.Axis = _axis.AddButton(Controllers.Controllers.TranslateInputKeysForInts(tempDown), Direction.Down, int.Parse(Global.PlayerSession.Data.GetString("P1JoystickNumber")));
                else if (tempDown.Contains("Key"))
                    movement.Axis = _axis.AddKey((Key)Controllers.Controllers.TranslateInputKeysForInts(tempDown), Direction.Down);
                else if (tempDown.Contains("Mouse"))
                    movement.Axis = _axis.AddMouseButton((MouseButton)Controllers.Controllers.TranslateInputKeysForInts(tempDown), Direction.Down);
                if (tempUp.Contains("Joy"))
                    movement.Axis = _axis.AddButton(Controllers.Controllers.TranslateInputKeysForInts(tempUp), Direction.Up, int.Parse(Global.PlayerSession.Data.GetString("P1JoystickNumber")));
                else if (tempUp.Contains("Key"))
                    movement.Axis = _axis.AddKey((Key)Controllers.Controllers.TranslateInputKeysForInts(tempUp), Direction.Up);
                else if (tempUp.Contains("Mouse"))
                    movement.Axis = _axis.AddMouseButton((MouseButton)Controllers.Controllers.TranslateInputKeysForInts(tempUp), Direction.Up);
                AddComponent(_axis);
            }
            #endregion
            //Console.WriteLine("currentAnim: {0}", _spriteMap.CurrentAnim);

        }//end of update
        public void PressKeysForAnimation(Controller cn, string l, string r, string u, string d, bool isStuck = false)
        {
            #region pressed Keys for animation
            if (cn.Button("P1Left").Pressed)//LEFT
            {
                Shared.ChangeAnimTo(l, _spriteMap);
                IsL = true; IsR = false; IsU = false; IsD = false;
            }
            else if (cn.Button("P1Right").Pressed)//RIGHT
            {
                Shared.ChangeAnimTo(r, _spriteMap);
                IsL = false; IsR = true; IsU = false; IsD = false;
            }
            else if (cn.Button("P1Up").Pressed)//UP
            {
                Shared.ChangeAnimTo(u, _spriteMap);
                IsL = false; IsR = false; IsU = true; IsD = false;
            }
            else if (cn.Button("P1Down").Pressed)//DOWN
            {
                Shared.ChangeAnimTo(d, _spriteMap);
                IsL = false; IsR = false; IsU = false; IsD = true;
            }
            #endregion
            #region released keys for animation
            if (cn.Button("P1Left").Released)//if i release left, updownright
            {
                if (cn.Button("P1Up").Down)//and i'm holding up
                {
                    Shared.ChangeAnimTo(u, _spriteMap);
                }
                else if (cn.Button("P1Down").Down)//and i'm holding down
                {
                    Shared.ChangeAnimTo(d, _spriteMap);
                }
                else if (cn.Button("P1Right").Down)//and i'm holding right
                {
                    Shared.ChangeAnimTo(r, _spriteMap);
                }
            }
            else if (cn.Button("P1Right").Released)//if i release right, updownleft
            {
                if (cn.Button("P1Up").Down)//and i'm holding up
                {
                    Shared.ChangeAnimTo(u, _spriteMap);
                }
                else if (cn.Button("P1Down").Down)//and i'm holding down
                {
                    Shared.ChangeAnimTo(d, _spriteMap);
                }
                else if (cn.Button("P1Left").Down)//and i'm holding left
                {
                    Shared.ChangeAnimTo(l, _spriteMap);
                }
            }
            else if (cn.Button("P1Up").Released)//if i release up, rightleftdown
            {
                if (cn.Button("P1Right").Down)//and i'm holding right
                {
                    Shared.ChangeAnimTo(r, _spriteMap);
                }
                else if (cn.Button("P1Left").Down)//and i'm holding left
                {
                    Shared.ChangeAnimTo(l, _spriteMap);
                }
                else if (cn.Button("P1Down").Down)//and i'm holding down
                {
                    Shared.ChangeAnimTo(d, _spriteMap);
                }
            }
            else if (cn.Button("P1Down").Released)//if i release down, rightleftup
            {
                if (cn.Button("P1Right").Down)//and i'm holding right
                {
                    Shared.ChangeAnimTo(r, _spriteMap);
                }
                else if (cn.Button("P1Left").Down)//and i'm holding left
                {
                    Shared.ChangeAnimTo(l, _spriteMap);
                }
                else if (cn.Button("P1Up").Down)//and i'm holding up
                {
                    Shared.ChangeAnimTo(u, _spriteMap);
                }
            }
            #endregion
        }

        public void StopWalkingAnimations()
        {
            if (!_hMove && !_vMove)
            {
                switch (_spriteMap.CurrentAnim)
                {
                    case ("walkLeft"):
                        _spriteMap.Play("standLeft");
                        break;
                    case ("walkRight"):
                        _spriteMap.Play("standRight");
                        break;
                    case ("walkUp"):
                        _spriteMap.Play("standUp");
                        break;
                    case ("walkDown"):
                        _spriteMap.Play("standDown");
                        break;
                    case ("flyLeft"):
                        _spriteMap.Play("flyLeft");
                        break;
                    case ("flyRight"):
                        _spriteMap.Play("flyRight");
                        break;
                    case ("flyUp"):
                        _spriteMap.Play("flyUp");
                        break;
                    case ("flyDown"):
                        _spriteMap.Play("flyDown");
                        break;
                    case ("flyFireGun"):
                        _spriteMap.Play("flyFireGun");
                        break;
                    default:
                        break;
                }
            }
        }

        public void ChangeAnimTo(string desiredAnimation)
        {
            if (_spriteMap.CurrentAnim != desiredAnimation)
                _spriteMap.Play(desiredAnimation);
        }
        #region AddSprites
        public void AddNewSprites()
        {
            var hMs = 4f;//horizontal animation speed
            _spriteMap.Add("standRight", new int[] { 0 }, new float[] { hMs, hMs });
            _spriteMap.Add("standLeft", new int[] { 0 }, new float[] { hMs, hMs });
            _spriteMap.Add("standUp", new int[] { 0 }, new float[] { hMs, hMs });
            _spriteMap.Add("standDown", new int[] { 0 }, new float[] { hMs, hMs });
            _spriteMap.Add("walkRight", new int[] { 0 }, new float[] { hMs, hMs });
            _spriteMap.Add("walkLeft", new int[] { 0 }, new float[] { hMs, hMs });
            _spriteMap.Add("walkUp", new int[] { 0 }, new float[] { hMs, hMs });
            _spriteMap.Add("walkDown", new int[] { 0 }, new float[] { hMs, hMs });
            _spriteMap.Add("flyRight", new int[] { 0, 1 }, new float[] { hMs, hMs });
            _spriteMap.Add("flyLeft", new int[] { 0, 1 }, new float[] { hMs, hMs });
            _spriteMap.Add("flyUp", new int[] { 0, 1 }, new float[] { hMs, hMs });
            _spriteMap.Add("flyDown", new int[] { 0, 1 }, new float[] { hMs, hMs });
            _spriteMap.Add("fireGun", new int[] { 2 }, new float[] { 5f, 5f });
            _spriteMap.Add("flyFireGun", new int[] { 2, 3 }, new float[] { 5f, 5f });
            _spriteMap.Add("death", new int[] { 4, 5 }, new float[] { 50f, 50f });
            _spriteMap.Add("dead", new int[] { 5 }, new float[] { 50f, 50f });
        }
        #endregion

        public override void Render()//mainly for testing colliders :D
        {
            base.Render();
            //Collider.Render();
            //jumpingCollider.Render(Color.Blue);
        }

        public void Destroy()
        {
            Global.GAME.RemoveScene();
            Global.GAME.AddScene(new LoseScreen());//change this to LEVELTWO when all the other things that make a game a game are in.
            RemoveSelf();
        }
    }
}
