using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MikuMikuDance.XNA.Model;

namespace MikuMikuDance.XNA.Accessory
{
    /// <summary>
    /// MikuMikuDanceのアクセサリデータ
    /// </summary>
    public class MMDAccessory : DrawableGameComponent
    {
        internal MMDModel parent = null;
        MikuMikuDanceXNA mmd = null;
        /// <summary>
        /// アクセサリに用いるモデルデータ
        /// </summary>
        public Microsoft.Xna.Framework.Graphics.Model ModelData { get; set; }
        /// <summary>
        /// このモデルに適応するワールド座標系
        /// </summary>
        public Matrix World { get; set; }
        
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="model">モデルデータ</param>
        /// <param name="mmd">MikuMikuDanceXNAオブジェクト</param>
        /// <param name="game">Gameオブジェクト</param>
        /// <param name="world">初期トランスフォームマトリックス</param>
        public MMDAccessory(Microsoft.Xna.Framework.Graphics.Model model,MikuMikuDanceXNA mmd, Game game,Matrix world)
            :base(game)
        {
            this.mmd = mmd;
            ModelData = model;
            World = world;
            game.Components.Add(this);
        }
        /// <summary>
        /// アクセサリの描画(DrawableGameComponent用
        /// </summary>
        /// <param name="gameTime">GameTimeオブジェクト</param>
        public override void Draw(GameTime gameTime)
        {
            //親がいない場合は自分で描画する。親がいる場合は親のタイミングで描画される
            if (parent == null)
                Draw(Matrix.Identity);
            base.Draw(gameTime);
        }
        /// <summary>
        /// 内部描画ルーチン
        /// </summary>
        /// <param name="baseTransform">基準トランスフォーム</param>
        internal void Draw(Matrix baseTransform)
        {
            //アクセサリ描画用に設定
            Game.GraphicsDevice.RenderState.AlphaBlendEnable = true;
            Game.GraphicsDevice.RenderState.BlendFunction = BlendFunction.Add;
            Game.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
            Game.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
            //モデルのCullModeを変更
            CullMode mode = Game.GraphicsDevice.RenderState.CullMode;
            Game.GraphicsDevice.RenderState.CullMode = CullMode.None;
            //ステージの描画
            foreach (ModelMesh mesh in ModelData.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.LightingEnabled = true;
                    //effect.EnableDefaultLighting();
                    effect.DirectionalLight0.Direction = mmd.LightManager.KeyLight.Direction;
                    effect.DirectionalLight0.Direction.Normalize();
                    effect.DirectionalLight0.DiffuseColor = mmd.LightManager.KeyLight.Color.ToVector3();
                    effect.DirectionalLight0.SpecularColor = Vector3.Zero;
                    effect.DirectionalLight0.Enabled = true;

                    effect.DirectionalLight1.Direction = mmd.LightManager.FillLight.Direction;
                    effect.DirectionalLight1.DiffuseColor = mmd.LightManager.FillLight.Color.ToVector3();
                    effect.DirectionalLight1.SpecularColor = Vector3.Zero;
                    effect.DirectionalLight1.Enabled = true;
                    effect.DirectionalLight2.Direction = mmd.LightManager.BackLight.Direction;
                    effect.DirectionalLight2.DiffuseColor = mmd.LightManager.BackLight.Color.ToVector3();
                    effect.DirectionalLight2.SpecularColor = Vector3.Zero;
                    effect.DirectionalLight2.Enabled = true;

                    effect.World = baseTransform * World;
                    effect.View = mmd.Camera.GetViewMatrix();
                    effect.Projection = mmd.Camera.GetProjectionMatrix(Game.GraphicsDevice);
                    
                }
                mesh.Draw();
            }
            //元に戻す
            Game.GraphicsDevice.RenderState.AlphaBlendEnable = false;
            //CullModeの変更を戻す
            Game.GraphicsDevice.RenderState.CullMode = mode;
            

        }

    }
}
