using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.IO;
using System.Threading;

namespace ImageTemplateNet
{
    /// <summary>
    /// Manages a thread that deletes old files from the cache directory if they have not been accessed in the last hour
    /// </summary>
    public class CachedFileManager
    {
        #region "Private Static Variables"
        /// <summary>
        /// Used to log error and debug messages
        /// </summary>
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(CachedFileManager));
        /// <summary>
        /// The instance of the Cached File Manager
        /// </summary>
        private static CachedFileManager s_Instance = new CachedFileManager();
        #endregion

        #region "Private Variables"
        /// <summary>
        /// The directory that files are cached to
        /// </summary>
        private DirectoryInfo m_cacheDir;
        /// <summary>
        /// True if the thread that is deleted unused files is running, false if the thread should stop
        /// </summary>
        private bool threadRunning = false;
        /// <summary>
        /// The thread that does the deleting
        /// </summary>
        Thread t;
        /// <summary>
        /// If a file has not been accessed in this many minutes then it will be deleted
        /// </summary>
        private int m_CachedFileMaximumAccessTimeMinutes;
        /// <summary>
        /// Makes sure that only one method in this class is trying to delete files at a time
        /// </summary>
        private object deleteFileLock = new object();
        #endregion

        #region "Constructors"
        /// <summary>
        /// Protected as this class is a singleton
        /// </summary>
        protected CachedFileManager()
        {

        }
        #endregion

        #region "Public Members"
        /// <summary>
        /// The instance of the cached file manager
        /// </summary>
        public static CachedFileManager Instance
        {
            get
            {
                return s_Instance;
            }
        }

        /// <summary>
        /// Starts the the thread that deletes old cached images
        /// </summary>
        public void Start()
        {
            t = new Thread(CleanDirectoryThreadEntry);
            t.Start();
        }

        /// <summary>
        /// Stops the cached file deletion thread
        /// </summary>
        public void Stop()
        {
            threadRunning = false;
        }

        /// <summary>
        /// Deletes any files in the cache directory.
        /// </summary>
        public void PurgeDirectory()
        {
            DirectoryInfo m_cacheDir = GetCacheDir();
            if (m_cacheDir.Exists)
            {
                lock (deleteFileLock)
                {
                    FileInfo[] files = m_cacheDir.GetFiles();
                    DateTime now = DateTime.Now;
                    foreach (FileInfo file in files)
                    {
                        try
                        {
                            file.Delete();
                        }
                        catch (Exception ex)
                        {
                            log.Error("Problem purging file from the cache", ex);
                        }
                    }
                }
            }
        }

        #endregion

        #region "Private Methods"
        /// <summary>
        /// Gets the directory which images should be cached into
        /// </summary>
        /// <returns></returns>
        private DirectoryInfo GetCacheDir()
        {
            if (this.m_cacheDir == null)
            {
                string cacheDir = ImageTemplateConfiguration.Instance.ImageCacheDirectoryPath;
                m_CachedFileMaximumAccessTimeMinutes = 60;
                DirectoryInfo cacheDirInfo = new System.IO.DirectoryInfo(cacheDir);
                m_cacheDir = cacheDirInfo;
            }
            return m_cacheDir;
        }

        /// <summary>
        /// Wakes up every X seconds and finds files that have not been accessed in X seconds and deletes them
        /// </summary>
        private void CleanDirectoryThreadEntry()
        {
            threadRunning = true;
            while (threadRunning)
            {
                DirectoryInfo m_cacheDir = GetCacheDir();
                if (m_cacheDir.Exists)
                {
                    lock (deleteFileLock)
                    {
                        FileInfo[] files = m_cacheDir.GetFiles();
                        DateTime now = DateTime.Now;
                        foreach (FileInfo file in files)
                        {
                            try
                            {
                                TimeSpan ts = now.Subtract(file.LastAccessTime);
                                if (ts.Minutes >= m_CachedFileMaximumAccessTimeMinutes) // If no one has tried to access the file in one hour then delete it.  We don't need it any more
                                {
                                    file.Delete();
                                }
                            }
                            catch (Exception ex)
                            {
                                log.Error("Problem deleting file from the cache", ex);
                            }
                        }
                    }
                }
                Thread.Sleep(60 * 1000); // Sleep for 60 seconds before looking for stuff to delete again
            }
        }
        #endregion
    }
}