using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using SkinnedModel;

namespace CharacterAnimation
{
   public class CharacterAnimationDemo : Microsoft.Xna.Framework.Game
   {
      GraphicsDeviceManager graphics;
      SpriteBatch spriteBatch;

      Vector3 cameraPos = new Vector3(0, 100, -100);
      Vector3 lookAtPos = new Vector3(0, 50, 0);
      Vector3 upDir = Vector3.UnitY;

      Model model;
      AnimationPlayer animationPlayer;
      
      
      public CharacterAnimationDemo()
      {
         graphics = new GraphicsDeviceManager(this);
         Content.RootDirectory = "Content";
         
         graphics.MinimumVertexShaderProfile = ShaderProfile.VS_2_0;
         graphics.MinimumPixelShaderProfile = ShaderProfile.PS_2_0;
      }


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


      protected override void LoadContent()
      {
         spriteBatch = new SpriteBatch(GraphicsDevice);

         model = Content.Load<Model>("dude");
         
         SkinningData skinningData = model.Tag as SkinningData;

         if(skinningData == null)
            throw new InvalidOperationException
               ("This model does not contain a SkinningData tag.");

         animationPlayer = new AnimationPlayer(skinningData);
         AnimationClip clip = skinningData.AnimationClips["Take 001"];

         animationPlayer.StartClip(clip);
      }


      protected override void UnloadContent()
      {

      }


      protected override void Update(GameTime gameTime)
      {
         if(Keyboard.GetState().IsKeyDown(Keys.Escape))
            this.Exit();

         animationPlayer.Update(gameTime.ElapsedGameTime, true,
                                Matrix.Identity);

         base.Update(gameTime);
      }


      protected override void Draw(GameTime gameTime)
      {
         graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
         float aspectRatio = GraphicsDevice.Viewport.AspectRatio;

         Matrix[] modelFinalBones = animationPlayer.GetSkinTransforms();
         
         Matrix view = Matrix.CreateLookAt(cameraPos,
                                           lookAtPos,
                                           upDir);

         Matrix proj = Matrix.CreatePerspectiveFieldOfView(
                       MathHelper.ToRadians(45.0f),
                       aspectRatio, 0.1f, 1000);

         foreach(ModelMesh mesh in model.Meshes)
         {
            foreach(Effect effect in mesh.Effects)
            {
               effect.Parameters["Bones"].SetValue(modelFinalBones);
               effect.Parameters["View"].SetValue(view);
               effect.Parameters["Projection"].SetValue(proj);
               
               mesh.Draw();
            }
         }

         base.Draw(gameTime);
      }
   }
}
