namespace Kit.Helpers.Cache
{
    using Microsoft.Extensions.Caching.Memory;
    using Kit.Helpers;
    using System;
    using System.Collections;
    using System.Collections.Generic;

    public interface IHttpCacheProvider : ICacheProvider { }

    public class MemoryCacheProvider : BaseCacheProvider, IHttpCacheProvider
    {
        private IMemoryCache _memoryCache;

        public MemoryCacheProvider(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }


        public override bool Contains(string cacheName)
        {
            cacheName = this.CacheNameNormalize(cacheName);
            object obj = null;
            return _memoryCache.TryGetValue(cacheName, out obj);
        }

        public override TResult GetCacheData<TResult>(string cacheName)
        {
            cacheName = CacheNameNormalize(cacheName);

            object? result = this._memoryCache.Get(cacheName);
            if (result == null) return default!;

            Check.IsTrue(result is TResult, $"Cache value has type:{result.GetType().FullName}. ArgumentType:{typeof(TResult).FullName}");

            return (TResult)result;
        }


        public override void PurgeCacheItems(string cacheName, bool isPrefix = false)
        {
            cacheName = CacheNameNormalize(cacheName);

            if (isPrefix)
            {
                var itemsToRemove = new List<string>();

                foreach (DictionaryEntry item in this._memoryCache.GetKeys())
                {
                    string key = item.Key.ToString()!;
                    if (key.StartsWith(cacheName))
                    {
                        itemsToRemove.Add(key);
                    }
                }
                //удаляем элементы кэша
                itemsToRemove.ForEach(x => this._memoryCache.Remove(x));
            }
            else
            {
                this._memoryCache.Remove(cacheName);
            }
        }

        public override void SetCacheData<TObject>(string cacheName, TObject data, MemoryCacheEntryOptions? setProperties = null, PostEvictionDelegate? callback = null)
        {
            if (data == null) return;
            cacheName = CacheNameNormalize(cacheName);

            if (setProperties == null)
            {
                setProperties = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(1) };
                setProperties.Priority = CacheItemPriority.Normal;
                if (callback != null)
                {
                    setProperties.RegisterPostEvictionCallback(callback);
                }
            }

            this._memoryCache.Set(cacheName, data, setProperties);
        }
    }
}