using System.IO;
using Encompass;
using KavTest.Components;
using KavTest.Engines;
using KavTest.Messages;
using KavTest.Renderers;
using KavTest.Spawners;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace KavTest
{
    class KavTestGame : Game
    {
        GraphicsDeviceManager graphics;

        WorldBuilder WorldBuilder { get; } = new WorldBuilder();
        World World { get; set; }

        public KavTestGame()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;
            graphics.PreferMultiSampling = true;
            Content.RootDirectory = "Content";

            Window.AllowUserResizing = true;
            IsMouseVisible = true;
        }

        protected override void LoadContent()
        {
            var rustyBallModel = Kav.ModelLoader.Load(
                GraphicsDevice,
                Smuggler.Importer.ImportGLB(GraphicsDevice, File.OpenRead("Content/rustysphere.glb"))
            );

            WorldBuilder.AddEngine(new InputEngine());
            WorldBuilder.AddEngine(new AngularVelocityEngine());
            WorldBuilder.AddEngine(new MotionEngine());
            WorldBuilder.AddEngine(new CameraEngine());
            WorldBuilder.AddEngine(new RustyBallSpawner(rustyBallModel));
            WorldBuilder.AddEngine(new LightBulbSpawner());
            WorldBuilder.AddGeneralRenderer(new SceneRenderer(GraphicsDevice), 0);

            WorldBuilder.SendMessage(new RustyBallSpawnMessage(
                new Transform3D(new Vector3(0, 0, 0)),
                new Vector3(1, 1, -1)
            ));

            WorldBuilder.SendMessage(new RustyBallSpawnMessage(
                new Transform3D(new Vector3(-3, 0, 0)),
                new Vector3(-1, 1, -1)
            ));

            WorldBuilder.SendMessage(new RustyBallSpawnMessage(
                new Transform3D(new Vector3(3, 0, 0)),
                new Vector3(-1, 1, 1)
            ));

            WorldBuilder.SendMessage(new LightBulbSpawnMessage(
                new Transform3D(new Vector3(0, 2, -5)),
                Color.White,
                300f
            ));

            var cameraTransform = new Transform3D(
                new Vector3(0, 0, -10),
                Quaternion.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi),
                Vector3.One
            );

            var cameraEntity = WorldBuilder.CreateEntity();
            WorldBuilder.SetComponent(cameraEntity, new Transform3DComponent(
                cameraTransform
            ));
            WorldBuilder.SetComponent(cameraEntity, new CameraComponent(
                Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.PiOver4,
                    16f / 9f,
                    0.1f,
                    200f
                )
            ));

            World = WorldBuilder.Build();
        }

        protected override void UnloadContent()
        {
            base.UnloadContent();
        }

        protected override void Update(GameTime gameTime)
        {
            World.Update(gameTime.ElapsedGameTime.TotalSeconds);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            World.Draw();

            base.Draw(gameTime);
        }
    }
}
