using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace MikuMikuDance.XNA.Builder.Build
{
    /// <summary>
    /// 一時ディレクトリヘルパークラス。singletonパターン
    /// </summary>
    class TempDirectoryHelper : IDisposable
    {
        //singleton
        static TempDirectoryHelper m_Instance = null;
        public static TempDirectoryHelper Instance
        {
            get
            {
                if (m_Instance == null)
                    m_Instance = new TempDirectoryHelper();
                return m_Instance;
            }
        }
        public static void DisposeStatic()
        {
            if (m_Instance != null)
            {
                m_Instance.Dispose();
                m_Instance = null;
            }
        }
        readonly string baseDir;
        readonly string buildDir;

        public string BaseDir { get { return baseDir; } }
        public string BuildDir { get { return buildDir; } }

        private TempDirectoryHelper()
        {
            //ディレクトリの既定を取得
            baseDir = Path.Combine(Path.GetTempPath(), GetType().FullName);
            //プロセスIDを取得して付加
            int processID = Process.GetCurrentProcess().Id;
            buildDir = Path.Combine(baseDir, processID.ToString());
            //一時ディレクトリの作成
            Directory.CreateDirectory(buildDir);

            PurgeStaleTempDirectories();
        }
        ~TempDirectoryHelper()
        {
            Dispose();
        }
        /// <summary>
        /// 一時ディレクトリが必要なくなった場合、それを削除します。
        /// </summary>
        void DeleteTempDirectory()
        {
            if (Directory.Exists(buildDir))
                Directory.Delete(buildDir, true);
            // 各自の一時ディレクトリをまだ使用しているプログラムのコピーが
            // ほかにない場合は、基本ディレクトリも削除できます。
            if (Directory.Exists(baseDir) && Directory.GetDirectories(baseDir).Length == 0)
            {
                Directory.Delete(baseDir);
            }
        }


        /// <summary>
        /// プログラムクラッシュやデバッガ停止による残存ディレクトリの削除
        /// </summary>
        void PurgeStaleTempDirectories()
        {
            // 基底の場所のサブディレクトリをすべて調べます。
            foreach (string directory in Directory.GetDirectories(baseDir))
            {
                // サブディレクトリ名は、作成したプロセスの ID になります。
                int processId;

                if (int.TryParse(Path.GetFileName(directory), out processId))
                {
                    try
                    {
                        // クリエーター プロセスはまだ実行していますか。
                        Process.GetProcessById(processId);
                    }
                    catch (ArgumentException)
                    {
                        // プロセスが存在しない場合、その一時ディレクトリを削除できます。
                        Directory.Delete(directory, true);
                    }
                }
            }
        }
        #region IDisposable メンバ

        public void Dispose()
        {
            DeleteTempDirectory();
        }

        #endregion
    }
}
