using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Caching;
using System.Web;
using System.IO;
using System.Text.RegularExpressions;

namespace CssSpriteGenerator
{
    public class CacheUtils
    {
        private const string _cacheNamePrefix = "___spritegen_";

        /// <summary>
        /// Defines all cache entry names. By having these in a central spot, there is less chance 
        /// of name clashes.
        /// </summary>
        public enum CacheEntryId
        {
            IsAnimated,
            OriginalImageSize, // The size (width and height) of the image as it lives on disk
            ImageFileSize,
            folderImagePaths,
            mappingInfos,
            hasFullTrust
        }

        /// <summary>
        /// Inserts a value into cache that is related to a particular file.
        /// Creates a file dependency for the cache item.
        /// </summary>
        /// <typeparam name="T">
        /// Type of the value
        /// </typeparam>
        /// <param name="cacheEntry">
        /// Identifies the cache entry
        /// </param>
        /// <param name="filePath">
        /// File path of the file this entry is related to
        /// </param>
        /// <param name="value">
        /// Value to insert
        /// </param>
        public static void InsertFileBasedEntry<T>(CacheEntryId cacheEntryId, string filePath, T value)
        {
            string cacheKey = CacheKey(cacheEntryId, filePath);

            CacheDependency cd = new CacheDependency(filePath);
            HttpContext.Current.Cache.Insert(cacheKey, value, cd);
        }

        /// <summary>
        /// Retrieves a file related cache entry with the given cache entry id and file path.
        /// 
        /// If the cache entry does not exist, the method returns default(T).
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cacheEntryId"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static T FileBasedEntry<T>(CacheEntryId cacheEntryId, string filePath)
        {
            string cacheKey = CacheKey(cacheEntryId, filePath);
            Object o = HttpContext.Current.Cache[cacheKey];
            if (o == null) { return default(T); }

            T result = (T)o;

            return result;
        }

        /// <summary>
        /// Inserts a cache entry.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cacheEntryId">
        /// Identifies the type of cache entry
        /// </param>
        /// <param name="additionalCacheKey">
        /// The cache key will be made up of standard elements plus this additional bit.
        /// </param>
        /// <param name="dependentFilesAndFolders">
        /// The cache entry will be invalidated if any of these files or folders are changed or deleted.
        /// If this is null, there will be no file dependencies.
        /// </param>
        /// <param name="value">
        /// </param>
        public static void InsertEntry<T>(CacheEntryId cacheEntryId, string additionalCacheKey, T value, string[] dependentFilesAndFolders)
        {
            string cacheKey = CacheKey(cacheEntryId, additionalCacheKey);
            if (dependentFilesAndFolders == null)
            {
                HttpContext.Current.Cache.Insert(cacheKey, value);
            }
            else
            {
                CacheDependency cd = new CacheDependency(dependentFilesAndFolders);
                HttpContext.Current.Cache.Insert(cacheKey, value, cd);
            }
        }

        /// <summary>
        /// Retrieves a cache entry with the given cache entry id and additional cache key.
        /// 
        /// If the cache entry does not exist, the method returns default(T).
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cacheEntryId"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static T Entry<T>(CacheEntryId cacheEntryId, string additionalCacheKey)
        {
            string cacheKey = CacheKey(cacheEntryId, additionalCacheKey);
            Object o = HttpContext.Current.Cache[cacheKey];
            if (o == null) { return default(T); }

            T result = (T)o;

            return result;
        }

        private static string CacheKey(CacheEntryId cacheEntryId, string additionalCacheKey)
        {
            string cacheKey = _cacheNamePrefix + ((int)cacheEntryId).ToString() + additionalCacheKey;
            return cacheKey;
        }
    }
}
