using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlimDX.Direct3D9;
using System.IO;
using System.Reflection;
using MikuMikuDance.SlimDX;
using SlimDX;
using System.Runtime.ConstrainedExecution;
using MikuMikuDance.Core.MultiThreads;

namespace MikuMikuDance.NiVE2
{
    class ObjectManager : CriticalFinalizerObject
    {
        public static ObjectManager m_inst = null;
        public static ObjectManager Instance
        {
            get
            {
                if (m_inst == null)
                {
                    m_inst = new ObjectManager();
                }
                return m_inst;
            }
        }
        public static void Init()
        {
            if (m_inst == null)
                m_inst = new ObjectManager();
        }
        FrmDummy dummyForm = new FrmDummy();
        Device device = null;
        PresentParameters pp;
        MMDNiVECamera camera = new MMDNiVECamera();
        MMDNiVELight light = new MMDNiVELight();
        bool LostDevice = false;
        public Device Device { get { return device; } }
        public MMDNiVECamera Camera { get { return camera; } }
        public MMDNiVELight Light { get { return light; } }

        private ObjectManager()
        {
            device = new Device(new Direct3D(), 0, DeviceType.Hardware, dummyForm.Handle, CreateFlags.HardwareVertexProcessing, pp = new PresentParameters()
            {
                BackBufferFormat = Format.X8R8G8B8,
                BackBufferCount = 1,
                Multisample = MultisampleType.FourSamples,
                SwapEffect = SwapEffect.Discard,
                EnableAutoDepthStencil = true,
                AutoDepthStencilFormat = Format.D16,
                PresentFlags = PresentFlags.DiscardDepthStencil,
                PresentationInterval = PresentInterval.Default,
                Windowed = true,
                DeviceWindowHandle = dummyForm.Handle,
                BackBufferWidth = MikuMikuDanceNiVE.Default.Width,
                BackBufferHeight = MikuMikuDanceNiVE.Default.Height
            });
            //トゥーンテクスチャのパスを準備(SlimMMDXではトゥーンフォルダを別に用意する必要がある)
            string[] toonTexPath = new string[10];
            string baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            for (int i = 1; i <= 10; ++i)
            {
                toonTexPath[i - 1] = Path.Combine(baseDir, Path.Combine("toons", "toon" + i.ToString("00") + ".bmp"));
            }
            //SlimMMDXのセットアップ(他の機能よりも先に使用する)
            SlimMMDXCore.Setup(device, toonTexPath);
            SlimMMDXCore.Instance.UsePhysics = false;
            SlimMMDXCore.Instance.OpaqueData.Add("StrictFaceVert", null);
            SlimMMDXCore.Instance.Camera = camera;
            SlimMMDXCore.Instance.Light = light;
            PhysicsThreadManager.Instanse.IsMultiThread = false;
        }
        
        ~ObjectManager()
        {
            SlimMMDXCore.Instance.Dispose();
            //SlimMMDXの解放処理
            foreach (var item in ObjectTable.Objects)
                item.Dispose();
        }
        public bool CheckLostDevice()
        {
            if (LostDevice)
            {
                if (ObjectManager.Instance.Device.TestCooperativeLevel() == ResultCode.DeviceNotReset)
                {
                    device.Reset(pp); 
                    SlimMMDXCore.Instance.OnResetDevice();
                    LostDevice = false;
                }
            }
            return LostDevice;
        }
        public void OnLostDevice()
        {
            SlimMMDXCore.Instance.OnLostDevice();
            LostDevice = true;
        }
    }
}
