using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;

using TImport = MikuMikuDance.Motion.Motion2.MMDMotion2;
using System.IO;

namespace MikuMikuDance.XNA.Motion
{
    /// <summary>
    /// テキストで書かれたモーションデータのインポート
    /// MMDでは作成できないようなモーションとか、簡易モーションとかを作るときに使用
    /// フォーマットは
    /// 1行目:ボーン数
    /// 2行目:ボーン名\tキーフレーム数
    /// 3行目〜:キーフレーム\tX移動,Y移動,Z移動\tX回転,Y回転,Z回転
    /// X行目〜次のボーン名\tキーフレーム数
    /// </summary>
    [ContentImporter(".vtmd", DisplayName = "MikuMikuDance Text Motion : MikuMikuDance for XNA", DefaultProcessor = "MMDMotionProcessor")]
    public class MMDTextMotionImporter : ContentImporter<TImport>
    {
        /// <summary>
        /// インポート処理
        /// </summary>
        /// <param name="filename">ファイル名</param>
        /// <param name="context">コンテキスト</param>
        /// <returns>MMDMotion2</returns>
        public override TImport Import(string filename, ContentImporterContext context)
        {
            TImport result = new MikuMikuDance.Motion.Motion2.MMDMotion2();
            ContentIdentity identity = new ContentIdentity(filename);
            using (StreamReader sr = File.OpenText(filename))
            {
                string line;
                int NumBone;
                line = sr.ReadLine();
                if (!int.TryParse(line, out NumBone))
                    throw new InvalidContentException("1行目はボーン数を整数で指定してください。" + line + "が指定されました", identity);
                //バッファの確保
                List<MikuMikuDance.Motion.Motion2.MotionData> data = new List<MikuMikuDance.Motion.Motion2.MotionData>();
                result.ModelName = null;
                result.LightMotions = new MikuMikuDance.Motion.Motion2.LightMotionData[0];
                result.FaceMotions = new MikuMikuDance.Motion.Motion2.FaceMotionData[0];
                result.CameraMotions = new MikuMikuDance.Motion.Motion2.CameraMotionData[0];
                for (int i = 0; i < NumBone; i++)
                {
                    int NumFrame;
                    string boneName;
                    line = sr.ReadLine();
                    string[] columns = line.Split('\t');
                    if (columns.Length < 2)
                        throw new InvalidContentException("ボーン名とキーフレーム数のフォーマットが一致しません", identity);
                    boneName = columns[0];
                    if (!int.TryParse(columns[1], out NumFrame))
                        throw new InvalidContentException("キーフレーム数を数値に変換できませんでした", identity);
                    for (int j = 0; j < NumFrame; j++)
                    {
                        MikuMikuDance.Motion.Motion2.MotionData mdata = new MikuMikuDance.Motion.Motion2.MotionData();
                        uint nFrame;
                        line = sr.ReadLine();
                        columns = line.Split('\t');
                        if (columns.Length < 3)
                            throw new InvalidContentException("キーフレーム\tX移動,Y移動,Z移動\tX回転,Y回転,Z回転のフォーマットと一致しません", identity);
                        if (!uint.TryParse(columns[0], out nFrame))
                            throw new InvalidContentException("キーフレームを数値に変換できませんでした", identity);
                        mdata.FrameNo = nFrame;
                        mdata.BoneName = boneName;
                        for (int k = 0; k < mdata.Interpolation.Length; k++)
                            for (int l = 0; l < mdata.Interpolation[k].Length; l++)
                                for (int m = 0; m < mdata.Interpolation[k][l].Length; m++)
                                    mdata.Interpolation[k][l][m] = 25;
                        string[] columns2 = columns[1].Split(',');
                        if (columns2.Length < 3)
                            throw new InvalidContentException("X移動,Y移動,Z移動のフォーマットと一致しません", identity);
                        for (int k = 0; k < 3; k++)
                        {
                            float fdata;
                            if (!float.TryParse(columns2[k], out fdata))
                                throw new InvalidContentException("移動量を浮動小数点に変換できませんでした", identity);
                            mdata.Location[k] = fdata;
                        }
                        columns2 = columns[2].Split(',');
                        if (columns2.Length < 3)
                            throw new InvalidContentException("X回転,Y回転,Z回転のフォーマットと一致しません", identity);
                        float[] fdatas = new float[3];
                        for (int k = 0; k < 3; k++)
                        {
                            if (!float.TryParse(columns2[k], out fdatas[k]))
                                throw new InvalidContentException("回転量を浮動小数点に変換できませんでした", identity);
                        }
                        Microsoft.Xna.Framework.Quaternion q = Quaternion.CreateFromYawPitchRoll(fdatas[1], fdatas[0], fdatas[2]);
                        mdata.Quatanion[0] = q.X;
                        mdata.Quatanion[1] = q.Y;
                        mdata.Quatanion[2] = q.Z;
                        mdata.Quatanion[3] = q.W;
                        data.Add(mdata);
                    }
                }
                sr.Close();
                //ソート。Lambda式でスッキリ。
                data.Sort((x, y) => (int)((long)x.FrameNo - (long)y.FrameNo));
                result.Motions = data.ToArray();
            }
            return result;
        }
    }
}
