using ThingsGateway.NewLife.Caching;

namespace ThingsGateway.SqlSugar
{
    public class ReflectionInoCacheService : ICacheService
    {
        public static ReflectionInoCacheService Instance { get; } = new ReflectionInoCacheService();

        public void Add<V>(string key, V value)
        {
            ReflectionInoCore<V>.GetInstance().Add(key, value);
        }

        public void Add<V>(string key, V value, int cacheDurationInSeconds)
        {
            ReflectionInoCore<V>.GetInstance().Add(key, value, cacheDurationInSeconds);
        }

        public bool ContainsKey<V>(string key)
        {
            return ReflectionInoCore<V>.GetInstance().ContainsKey(key);
        }

        public V Get<V>(string key)
        {
            return ReflectionInoCore<V>.GetInstance().Get(key);
        }

        public IEnumerable<string> GetAllKey<V>()
        {
            return ReflectionInoCore<V>.GetInstance().GetAllKey();
        }

        public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue)
        {
            return ReflectionInoCore<V>.GetInstance().GetOrCreate(cacheKey, create);
        }

        public void Remove<V>(string key)
        {
            ReflectionInoCore<V>.GetInstance().Remove(key);
        }
    }
    public class ReflectionInoCore<V>
    {
        private MemoryCache InstanceCache => MemoryCache.Instance;
        private static ReflectionInoCore<V> _instance = null;
        private static readonly object _instanceLock = new object();
        private ReflectionInoCore() { }

        public V this[string key]
        {
            get
            {
                return this.Get(key);
            }
        }

        public bool ContainsKey(string key)
        {
            return this.InstanceCache.ContainsKey(key);
        }

        public V Get(string key)
        {
            return this.InstanceCache.Get<V>(key);
        }

        public static ReflectionInoCore<V> GetInstance()
        {
            if (_instance == null)
                lock (_instanceLock)
                    if (_instance == null)
                    {
                        _instance = new ReflectionInoCore<V>();
                        Action addItem = () => { ReflectionInoCore<V>.GetInstance().RemoveAllCache(); };
                        ReflectionInoHelper.AddRemoveFunc(addItem);
                    }
            return _instance;
        }

        public void Add(string key, V value)
        {
            this.InstanceCache.GetOrAdd<V>(key, (s) => value);
        }

        public void Add(string key, V value, int cacheDurationInSeconds)
        {
            Check.ThrowNotSupportedException("ReflectionInoCache.Add(string key, V value, int cacheDurationInSeconds)");
        }

        public void Remove(string key)
        {
            this.InstanceCache.Remove(key);
        }

        public void RemoveAllCache()
        {
            foreach (var key in GetAllKey())
            {
                this.Remove(key);
            }
        }

        public IEnumerable<string> GetAllKey()
        {
            return this.InstanceCache.Keys;
        }

        public V GetOrCreate(string cacheKey, Func<V> create)
        {
            return InstanceCache.GetOrAdd<V>(cacheKey, (a) => create());
        }
    }
    public static class ReflectionInoHelper
    {
        private static List<Action> removeActions = new List<Action>();
        internal static void AddRemoveFunc(Action removeAction)
        {
            removeActions.Add(removeAction);
        }

        public static void RemoveAllCache()
        {
            lock (removeActions)
            {
                foreach (var item in removeActions)
                {
                    item();
                }
            }
        }
    }
}
