using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Innovation;
using System;

namespace TestEnvironment
{
    public class Game1 : Game
    {
        // The IGraphicsDeviceService the engine will use
        GraphicsDeviceManager graphics;
        Terrain terr;

        public Game1()
        {
            // Setup graphics
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = (int)(1280 * .75f);
            graphics.PreferredBackBufferHeight = (int)(760 * .75f);
        }

        protected override void LoadContent()
        {
            // Setup engine. We do this in the load method
            // so that we know graphics will be ready for use
            Engine.SetupEngine(graphics);

            // Create a new Camera
            FPSCamera camera = new FPSCamera();

            // Setup its position and target
            camera.Position = new Vector3(138.2664f, 37.25768f, 128.8698f);
            camera.RotateTranslate(new Vector3(-.1417831f * 2f, .4225208f * 2, 0), Vector3.Zero);

            // Add it to the service container
            Engine.Services.AddService(typeof(Camera), camera);

            // Setup physics
            new Physics();

            MouseDevice mouse = new MouseDevice();
            KeyboardDevice keyboard = new KeyboardDevice();

            Engine.Services.AddService(typeof(MouseDevice), mouse);
            Engine.Services.AddService(typeof(KeyboardDevice), keyboard);

            PhysicsActor act = new PhysicsActor(
                    "Content/ig_box",
                    new BoxObject(new Vector3(2.5f), new Vector3(256, 100, 256), Vector3.Zero));

            act.Scale = new Vector3(2.5f);
            act.PhysicsObject.Mass = 1000;
        }

        int count = 0;

        protected override void Update(GameTime gameTime)
        {
            count++;

            if (count == 2)
                terr = new Terrain();
            else if (count == 4)
                terr.Heightmap = "Content/Heightmap";

            // Update the engine and game
            Engine.Update(gameTime);

            KeyboardDevice keyboard = Engine.Services.GetService<KeyboardDevice>();
            MouseDevice mouse = Engine.Services.GetService<MouseDevice>();
            FPSCamera cam = (FPSCamera)Engine.Services.GetService<Camera>();

            Vector3 inputModifier = new Vector3(
                (keyboard.IsKeyDown(Keys.A) ? -1 : 0) + (keyboard.IsKeyDown(Keys.D) ? 1 : 0),
                (keyboard.IsKeyDown(Keys.Q) ? -1 : 0) + (keyboard.IsKeyDown(Keys.E) ? 1 : 0),
                (keyboard.IsKeyDown(Keys.W) ? -1 : 0) + (keyboard.IsKeyDown(Keys.S) ? 1 : 0)
            );

            cam.RotateTranslate(new Vector3(mouse.Delta.Y * -.002f, mouse.Delta.X * -.002f, 0), inputModifier * .5f);

            bool left = mouse.WasButtonPressed(MouseButtons.Left);
            bool right = mouse.WasButtonPressed(MouseButtons.Right);

            if (left || right)
            {
                PhysicsActor act = new PhysicsActor(
                    (left ? "Content/ig_box" : "Content/capsule"),
                    (left ? (PhysicsObject)new BoxObject(new Vector3(1.0f), cam.Position, Vector3.Zero) : (PhysicsObject)new CapsuleObject(3f, 1f, cam.Position, Vector3.Zero)));

                if (act is BoxObject)
                {
                    ((BoxObject)act.PhysicsObject).SideLengths = new Vector3(2.5f);
                    act.Scale = new Vector3(2.5f);
                }

                act.PhysicsObject.Mass = 4000;

                Vector3 dir = cam.Target - cam.Position;
                dir.Normalize();

                act.PhysicsObject.Velocity = dir * 10;
            }

            if (keyboard.WasKeyReleased(Keys.P) && keyboard.IsKeyDown(Keys.LeftControl))
            {
                Engine.Services.GetService<Camera>().Serialize = false;
                Engine.SerializeState("serialized.txt");
            }
            if (keyboard.WasKeyReleased(Keys.O) && keyboard.IsKeyDown(Keys.LeftControl))
            {
                Engine.Reset();
                MouseDevice newMouse = new MouseDevice();
                KeyboardDevice newKeyboard = new KeyboardDevice();

                Engine.Services.AddService(typeof(MouseDevice), newMouse);
                Engine.Services.AddService(typeof(KeyboardDevice), newKeyboard);

                // Create a new Camera
                FPSCamera newCamera = new FPSCamera();

                // Setup its position and target
                newCamera.Position = new Vector3(138.2664f, 37.25768f, 128.8698f);
                newCamera.RotateTranslate(new Vector3(-.1417831f * 2f, .4225208f * 2, 0), Vector3.Zero);

                // Add it to the service container
                Engine.Services.AddService(typeof(Camera), newCamera);
            }

            if (keyboard.WasKeyReleased(Keys.I) && keyboard.IsKeyDown(Keys.LeftControl))
                Engine.DeserializeState("serialized.txt");

            if (keyboard.WasKeyReleased(Keys.D1))
            {
                for (int x = 0; x < 3; x++)
                {
                    for (int y = 0; y < 16; y++)
                    {
                        PhysicsActor act = new PhysicsActor(
                            "Content/ig_box",
                            new BoxObject(new Vector3(2.5f), new Vector3(x * 2.5f + 128, y * 2.5f, 128), Vector3.Zero));

                        act.Scale = new Vector3(2.5f);
                        act.PhysicsObject.Mass = 1000;
                    }
                }
            }

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            if (count == 2)
                terr.Texture = "Content/grass";

            // Draw the engine and game
            Engine.Draw(gameTime, ComponentType.All);
        }
    }
}