using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content.Pipeline;
using MikuMikuDance.XNA.Motion.MotionData;
using TInput = MikuMikuDance.Motion.Motion2.MMDMotion2;
using TOutput = MikuMikuDance.XNA.Motion.MotionData.MMDMotionData;
using System;

namespace MikuMikuDance.XNA.Motion
{
    /// <summary>
    /// MikuMikuDanceのモーションデータデータをXNAにインポートするためのプロセッサ
    /// </summary>
    [ContentProcessor(DisplayName = "MikuMikuDanceモーション : MikuMikuDance for XNA")]
    public class MMDMotionProcessor : ContentProcessor<TInput, TOutput>
    {
        /// <summary>
        /// コンテンツ変換
        /// </summary>
        /// <param name="input">MMDモーションデータ</param>
        /// <param name="context">コンテントプロセッサ</param>
        /// <returns>MMDモーションデータ for XNA</returns>
        public override TOutput Process(TInput input, ContentProcessorContext context)
        {
            TOutput result = new TOutput();
            //ボーンモーションデータの変換
            result.BoneMotions = new MMDBoneMotion[input.Motions.LongLength];
            if (result.BoneMotions.LongLength > int.MaxValue)
                throw new InvalidContentException("ボーンモーション数が多すぎます。MikuMikuDanceXNAは.NET Compact Frameworkの制限のため、32bit符号付き整数最大値までしかモーション数をサポートしていません");
            for (long i = 0; i < result.BoneMotions.LongLength; i++)
            {
                result.BoneMotions[i] = new MMDBoneMotion();
                result.BoneMotions[i].BoneName = input.Motions[i].BoneName;
                result.BoneMotions[i].FrameNo = input.Motions[i].FrameNo;

                result.BoneMotions[i].Curve = new BezierCurve[4];
                for (int j = 0; j < result.BoneMotions[i].Curve.Length; j++)
                {
                    BezierCurve curve = new BezierCurve();
                    curve.v1 = new Vector2((float)input.Motions[i].Interpolation[0][0][j] / 128f, (float)input.Motions[i].Interpolation[0][1][j] / 128f);
                    curve.v2 = new Vector2((float)input.Motions[i].Interpolation[0][2][j] / 128f, (float)input.Motions[i].Interpolation[0][3][j] / 128f);
                    result.BoneMotions[i].Curve[j] = curve;
                }

                result.BoneMotions[i].Location = new Vector3(input.Motions[i].Location[0], input.Motions[i].Location[1], input.Motions[i].Location[2]);
                result.BoneMotions[i].Quatanion = new Quaternion(input.Motions[i].Quatanion[0], input.Motions[i].Quatanion[1], input.Motions[i].Quatanion[2], input.Motions[i].Quatanion[3]);
            }
            //表情モーションの変換
            result.FaceMotions = new MMDFaceMotion[input.FaceMotions.LongLength];
            if (result.FaceMotions.LongLength > int.MaxValue)
                throw new InvalidContentException("表情モーション数が多すぎます。MikuMikuDanceXNAは.NET Compact Frameworkの制限のため、32bit符号付き整数最大値までしかモーション数をサポートしていません");
            for (long i = 0; i < input.FaceMotions.Length; i++)
            {
                result.FaceMotions[i] = new MMDFaceMotion();
                result.FaceMotions[i].Rate = input.FaceMotions[i].Rate;
                result.FaceMotions[i].FaceName = input.FaceMotions[i].FaceName;
                result.FaceMotions[i].FrameNo = input.FaceMotions[i].FrameNo;
                float temp = input.FaceMotions[i].FrameNo;
            }
            //カメラモーションの変換
            result.CameraMotions = new MMDCameraMotion[input.CameraMotions.LongLength];
            if (result.CameraMotions.LongLength > int.MaxValue)
                throw new InvalidContentException("カメラモーション数が多すぎます。MikuMikuDanceXNAは.NET Compact Frameworkの制限のため、32bit符号付き整数最大値までしかモーション数をサポートしていません");
            for (long i = 0; i < input.CameraMotions.Length; i++)
            {
                result.CameraMotions[i] = new MMDCameraMotion();
                result.CameraMotions[i].FrameNo = input.CameraMotions[i].FrameNo;
                result.CameraMotions[i].Length = input.CameraMotions[i].Length;
                result.CameraMotions[i].Location = MMDMath.VectorFromArray(input.CameraMotions[i].Location);
                result.CameraMotions[i].Quatanion = Quaternion.CreateFromYawPitchRoll(input.CameraMotions[i].Rotate[1], input.CameraMotions[i].Rotate[0], input.CameraMotions[i].Rotate[2]);
                result.CameraMotions[i].ViewAngle = MathHelper.ToRadians(input.CameraMotions[i].ViewingAngle);
                result.CameraMotions[i].Curve = new BezierCurve[6];
                for (int j = 0; j < result.CameraMotions[i].Curve.Length; j++)
                {
                    BezierCurve curve = new BezierCurve();
                    curve.v1 = new Vector2((float)input.CameraMotions[i].Interpolation[j][0] / 128f, (float)input.CameraMotions[i].Interpolation[j][2] / 128f);
                    curve.v2 = new Vector2((float)input.CameraMotions[i].Interpolation[j][1] / 128f, (float)input.CameraMotions[i].Interpolation[j][3] / 128f);
                    result.CameraMotions[i].Curve[j] = curve;
                }
            }
            //ライトモーションの変換
            result.LightMotions = new MMDLightMotion[input.LightMotions.LongLength];
            if (result.LightMotions.LongLength > int.MaxValue)
                throw new InvalidContentException("ライトモーション数が多すぎます。MikuMikuDanceXNAは.NET Compact Frameworkの制限のため、32bit符号付き整数最大値までしかモーション数をサポートしていません");
            for (long i = 0; i < input.LightMotions.Length; i++)
            {
                result.LightMotions[i] = new MMDLightMotion();
                result.LightMotions[i].FrameNo = input.LightMotions[i].FrameNo;
                result.LightMotions[i].Color = MMDMath.VectorFromArray(input.LightMotions[i].Color);
                result.LightMotions[i].Location = MMDMath.VectorFromArray(input.LightMotions[i].Location);
            }
            //XNA用に変換したデータを返却
            return result;
        }
    }
}