using LHDN.CRM.BC.Common;
using LHDN.CRM.Models.ViewModels;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

namespace LHDN.CRM.BC.Services
{
    public class CachingService
    {
        internal static ObjectCache _cache = MemoryCache.Default;
        private const int defaultCacheDuration = 60;

        public static bool TryGet<T>(string cacheKey, out T cacheItem)
        {
            cacheItem = (T)_cache[cacheKey];
            return cacheItem != null;
        }

        public static bool ClearAll()
        {
            List< string > cacheKeys = _cache.Select(kvp => kvp.Key).ToList();
            foreach (string cacheKey in cacheKeys)
            {
                _cache.Remove(cacheKey);
            }
            return true;
        }

        public static bool Clear(string cacheKey)
        {
            return _cache.Select(kvp => kvp.Key).ToList().Remove(cacheKey);
        }

        public static bool TrySetOrUpdate<T>(string cacheKey, Func<T> getItem, out T returnData, int? cacheDuration = null, CacheItemPolicy policy = null)
        {
            returnData = default(T);
            //LogWriter.LogMessage("TrySetOrUpdate : " + cacheKey);
            if (_cache.Contains(cacheKey))
            {
                //LogWriter.LogMessage("Contains cache item");
                _cache.Remove(cacheKey);
                //LogWriter.LogMessage("Removed cache item");
                CacheItemPolicy p = policy ?? new CacheItemPolicy() { AbsoluteExpiration = DateTime.Now.AddSeconds(cacheDuration.HasValue ? cacheDuration.Value : defaultCacheDuration) };
                // Reset cache item
                returnData = getItem();
                //LogWriter.LogMessage("Get new cache item");
                if (returnData != null)
                {
                    //LogWriter.LogMessage("Return Value not null");
                    _cache.Add(cacheKey,  returnData, p);
                }

                //LogWriter.LogMessage("return result" + Convert.ToBoolean(returnData != null).ToString());
                return returnData != null;
            }
            //else
            //{
            //    LogWriter.LogMessage("No cache item");
            //}        

            return true;
        }


        public static bool TryGetOrAdd<T>(string cacheKey, Func<T> getItem, out T returnData, int? cacheDuration = null, CacheItemPolicy policy = null)
        {
            if (TryGet<T>(cacheKey, out returnData))
            {
                return true;
            }

            CacheItemPolicy p = policy ?? new CacheItemPolicy() { AbsoluteExpiration = DateTime.Now.AddSeconds(cacheDuration.HasValue ? cacheDuration.Value : defaultCacheDuration) };
            returnData = getItem();

            if (returnData != null)
            {
                _cache.Add(cacheKey, returnData, p);
            }

            return returnData != null;

        }
        public static Dictionary<string, T> ContainsKey<T>(string cacheKey)
        {
            Dictionary<string, T> dicObj = _cache.AsEnumerable().Where(x => x.Key.Contains(cacheKey)).ToDictionary(x=> x.Key, x=>(T)x.Value);

            return dicObj;
        }
        //public static bool TryGetOrAdd<T>(string cacheKey, Func<T> getItem, out T returnData, CacheItemPolicy policy = null)
        //{
        //    if (TryGet<T>(cacheKey, out returnData))
        //    {
        //        return true;
        //    }

        //    CacheItemPolicy p = policy ?? new CacheItemPolicy() { AbsoluteExpiration = DateTime.Now.AddSeconds(defaultCacheDuration) };
        //    returnData = getItem();

        //    if (returnData != null)
        //    {
        //        _cache.Add(cacheKey, returnData, p);
        //    }

        //    return returnData != null;

        //}


    }
}
