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

namespace MikuMikuDance.XNA.Model
{
    /// <summary>
    /// 剛体クラス
    /// </summary>
    abstract class MMDPhysicsObject
    {
        public RigidBody body { get; protected set; }
        public ICollisionShape collision { get; protected set; }
        public MMDRigid Rigid { get; protected set; }
        protected MMDModel Model;
        protected UInt16 RelatedBone;
        
        protected Vector3 defaultPos = Vector3.Zero;
        protected Quaternion defaultRotate = Quaternion.Identity;
        
        
        protected DefaultMotionState motionStateStart;

        public MMDPhysicsObject(MMDRigid rigid, MMDModel model)
        {
            Model = model;
            Rigid = rigid;
        }
        public static MMDPhysicsObject PhisicsObjectFactory(MMDRigid rigid, MMDModel model, DiscreteDynamicsWorld world)
        {
            switch (rigid.ShapeType)
            {
                case 0://球
                    return new MMDPhysicsSphere(rigid, model, world);
                case 1://箱
                    return new MMDPhysicsBox(rigid, model, world);
                case 2://カプセル
                    return new MMDPhysicsCapsule(rigid, model, world);
                default:
                    throw new ApplicationException("Undefined Rigid Shape Type");
            }
        }

        /// <summary>
        /// 剛体→ボーンへの適応
        /// </summary>
        internal virtual void ApplyRigitToBone() 
        {
            if (before != -1)
            {
                if (count > 0)
                    count--;
                else
                {
                    body.ResetVelocity();
                    body.ForceActivationState(before);
                    body.Activate(true);
                    body.ResetVelocity();
                    before = -1;
                }
            }
        }
        /// <summary>
        /// ボーン→剛体への適応
        /// </summary>
        internal virtual void ApplyBoneToRigit() { }
        
        protected Matrix CreateOrientation(MMDRigid rigid)
        {
            return Matrix.CreateFromYawPitchRoll(rigid.Rotation[1],rigid.Rotation[0],rigid.Rotation[2])
                * Matrix.CreateTranslation(rigid.Position[0], rigid.Position[1], rigid.Position[2]);
        }
        int before = -1;
        int count = 0;
        internal void ResetRigid()
        {
            if (Rigid.RelatedBoneIndex != 0xffff)
            {
                //count = 100;
                //before = body.GetActivationState();
                //body.SetActivationState(body.GetActivationState() | 4);
                Matrix mat;
                mat = body.GetWorldTransform();
                mat = CreateOrientation(Rigid) *
                            Model.BoneManager.Bones[Rigid.RelatedBoneIndex].WorldTransform.CreateMatrix() * Model.World;
                body.Activate(true);
                body.SetWorldTransform(mat);
                body.ResetVelocity();
                //body.ForceActivationState(before);
                //body.SetWorldTransform(CreateOrientation(Rigid) *
                //        Model.BoneManager.Bones[Rigid.RelatedBoneIndex].WorldTransform.CreateMatrix() * Model.World);
                //body.SetActivationState(1);
            }
        }
    }
    class MMDPhisicsSorter : IComparer<MMDPhysicsObject>
    {
        public int Compare(MMDPhysicsObject o1, MMDPhysicsObject o2)
        {
            return o1.Rigid.RelatedBoneIndex - o2.Rigid.RelatedBoneIndex;
        }
    }
}
