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>
        /// MikuMikuDanceXNA.TimeRularをこのアクセサリが呼び出すかどうか
        /// </summary>
        public bool UseTimeRular { 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;
            UseTimeRular = true;
            game.Components.Add(this);
            //アクセサリの初期設定
            foreach (ModelMesh mesh in ModelData.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.LightingEnabled = true;
                    effect.DirectionalLight0.Enabled = true;
                    effect.DirectionalLight1.Enabled = false;
                    effect.DirectionalLight2.Enabled = false;
                    
                }
            }
        }
        /// <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)
        {
            if (mmd.TimeRular != null && UseTimeRular)
            {
                mmd.TimeRular.BeginMark(0, "DrawAccessory", Color.Yellow);
            }
            //アクセサリ描画用に設定
            Game.GraphicsDevice.RenderState.AlphaBlendEnable = true;
            Game.GraphicsDevice.RenderState.BlendFunction = BlendFunction.Add;
            Game.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
            Game.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
            Game.GraphicsDevice.RenderState.AlphaTestEnable = true;
            Game.GraphicsDevice.RenderState.ReferenceAlpha = 1;
            Game.GraphicsDevice.RenderState.AlphaFunction = CompareFunction.GreaterEqual;
            
            //モデルのCullModeを変更
            CullMode mode = Game.GraphicsDevice.RenderState.CullMode;
            Game.GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
            //アクセサリの描画
            foreach (ModelMesh mesh in ModelData.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.AmbientLightColor = mmd.LightManager.AmbientLight.ToVector3();
                    effect.DirectionalLight0.Direction = mmd.LightManager.KeyLight.Direction;
                    effect.DirectionalLight0.Direction.Normalize();
                    effect.DirectionalLight0.DiffuseColor = mmd.LightManager.KeyLight.Color.ToVector3();//new Vector3(0.2f, 0.2f, 0.2f);
                    effect.DirectionalLight0.SpecularColor = mmd.LightManager.KeyLight.Color.ToVector3();
                    effect.World = World * baseTransform;
                    effect.View = mmd.Camera.GetViewMatrix();
                    effect.Projection = mmd.Camera.GetProjectionMatrix(Game.GraphicsDevice);
                }
                mesh.Draw();
            }
            //CullModeの変更を戻す
            Game.GraphicsDevice.RenderState.CullMode = mode;
            if (mmd.TimeRular != null && UseTimeRular)
            {
                mmd.TimeRular.EndMark(0, "DrawAccessory");
            }
        }

    }
}
