using System;
using MikuMikuDance.XNA.Model.ModelData;
using Microsoft.Xna.Framework;
using BulletCLI;
using Microsoft.Xna.Framework.Graphics;
//using BulletX.Dynamics;
//using BulletX;

namespace MikuMikuDance.XNA.Model
{
    /// <summary>
    /// ボックス型剛体クラス
    /// </summary>
    class MMDPhysicsBox : MMDPhysicsObject
    {
        public MMDPhysicsBox(MMDRigid rigid, MMDModel model, DiscreteDynamicsWorld world)
            : base(rigid, model)
        {
            collision = new BoxShape(new Vector3(rigid.ShapeWidth, rigid.ShapeHeight, rigid.ShapeDepth));
            //初期の姿勢を計算
            Matrix startTransform;
            if (rigid.RelatedBoneIndex != 0xffff)
                startTransform = model.BoneManager.Bones[rigid.RelatedBoneIndex].WorldTransform.CreateMatrix();
            else
            {
                if (model.BoneManager.ContainsBone("センター"))
                    startTransform = model.BoneManager.Bones[model.BoneManager.IndexOf("センター")].WorldTransform.CreateMatrix();
                else
                    startTransform = Matrix.Identity;
            }
            startTransform = CreateOrientation(rigid) * startTransform * Model.World;

            //初期の姿勢をMotionStateに設定
            motionStateStart = new DefaultMotionState(startTransform, Matrix.Identity);


            Vector3 localInertia = Vector3.Zero;
            //イナーシャの計算
            if (rigid.Type != 0)
                collision.CalculateLocalInertia(rigid.Weight, out localInertia);
            //関連ボーン番号を取得しておく
            RelatedBone = rigid.RelatedBoneIndex;
            //body.DoShockProcessing = false;
            //body.Immovable = true;
            //剛体を作成
            body = new RigidBody((rigid.Type != 0?rigid.Weight:0), motionStateStart, collision, localInertia);
            //ダンピング値、摩擦、Restitutionをセット
            body.SetDamping(rigid.LinerDamping, rigid.AngularDamping);
            body.SetFriction(rigid.Friction);
            body.SetRestitution(rigid.Restitution);
            //ボーン追従型はImmovableにする
            if (rigid.Type == 0)
            {
                body.SetActivationState(body.GetActivationState() | 4);
                body.SetCollisionFlags(CollisionFlags.CF_KINEMATIC_OBJECT);
            }
            //グループのフラグをセット
            short group = (short)Math.Pow(2, Rigid.GroupIndex);

            //ボディを有効化し、グループとマスクをセット
            world.AddRigidBody(body, group, (short)rigid.GroupTarget);
        }
        internal override void ApplyRigitToBone()
        {
            if (RelatedBone == 0xffff)
                return;
            if (Rigid.Type != 0 && Rigid.RelatedBoneIndex < Model.BoneManager.Bones.Length)
            {
                Matrix RigidPos = body.GetWorldTransformSmart();
                Model.BoneManager.Bones[Rigid.RelatedBoneIndex].WorldTransform = QuatTransform.FromMatrix(Matrix.Invert(CreateOrientation(Rigid)) * RigidPos * Matrix.Invert(Model.World));
            }
            base.ApplyRigitToBone();
        }
        internal override void ApplyBoneToRigit()
        {
            if (RelatedBone == 0xffff)
                return;
            if (Rigid.Type == 0 && Rigid.RelatedBoneIndex < Model.BoneManager.Bones.Length)
            {
                body.SetWorldTransformByMotionState(CreateOrientation(Rigid) *
                    Model.BoneManager.Bones[Rigid.RelatedBoneIndex].WorldTransform.CreateMatrix() * Model.World);
            }
            base.ApplyBoneToRigit();
        }
        
    }
}
