using System.IO;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using System.ComponentModel;
using Microsoft.Xna.Framework.Content;


namespace MikuMikuDance.XNA.Model
{
    /// <summary>
    /// /// コンテント・パイプライン内の中間データであるNodeContentから
    /// アニメーションデータを含んだModelContentへ変換するプロセッサ
    /// </summary>
    [ContentProcessor]
    internal class SkinnedModelProcessor : ModelProcessor
    {
        [DefaultValue("")]
        public string EffectFile { get; set; }

        /// <summary>
        /// コンテント・パイプライン内の中間データであるNodeContentから
        /// アニメーションデータを含んだModelContentへ変換するProcessメソッド。
        /// メイン処理はMMDProcessorに任せて、ここではエフェクト周りのプロセスを行う
        /// </summary>
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            // ベースクラスのProcessメソッドを呼び出してモデルデータを変換する
            return base.Process(input, context);
        }

        /// <summary>
        /// 全てのマテリアルがスキンモデル用のエフェクトを使うように変更する
        /// </summary>
        protected override MaterialContent ConvertMaterial(MaterialContent material,
                                                        ContentProcessorContext context)
        {
            BasicMaterialContent basicMaterial = material as BasicMaterialContent;
            EffectMaterialContent effectMaterial;
            // スキンメッシュエフェクトを参照する
            
            ExternalReference<EffectContent> effect;
            if (EffectFile == "")
            {
                //リソースからファイルを作成して読み込むという超セコイ方法……
                if (!Directory.Exists("ext"))
                    Directory.CreateDirectory("ext");
                FileStream fs = new FileStream(Path.Combine("ext", "MMDModel.fx"), FileMode.Create);
                BinaryWriter bw = new BinaryWriter(fs);
                bw.Write(Resource1.MMDModel);
                bw.Close();
                effect = new ExternalReference<EffectContent>(Path.Combine("ext", "MMDModel.fx"));
                //effect = new ExternalReference<EffectContent>("MMDModel.fx");
            }
            else
                effect = new ExternalReference<EffectContent>(Path.GetFullPath(EffectFile));
            
            if (basicMaterial == null)
            {
                effectMaterial = material as EffectMaterialContent;
                if (effectMaterial == null)
                    throw new InvalidContentException(string.Format(
                    "MMDProcessorはEffectMaterialContentまたはBasicMaterialContentのみをサポートします" +
                    "入力メッシュは{0}を使用しています。", material.GetType()));
                // スキンメッシュエフェクトを埋め込む
                effectMaterial.Effect = effect;
                ResizeTexturesToPowerOfTwo = true;
                //　ModelProcessorのConvertMaterialを呼ぶ
                return base.ConvertMaterial(effectMaterial, context);
            }
            else
            {

                effectMaterial = new EffectMaterialContent();

                // スキンメッシュエフェクトを埋め込む
                effectMaterial.Effect = effect;
                
                // BasicMaterialContentのテクスチャを新しいマテリアルに設定する
                if (basicMaterial.Texture != null)
                    effectMaterial.Textures.Add("Texture", basicMaterial.Texture);
                ResizeTexturesToPowerOfTwo = true;
                
                //　ModelProcessorのConvertMaterialを呼ぶ
                return base.ConvertMaterial(effectMaterial, context);
            }
        }
    }
}