using Managing.Application.Abstractions.Services;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;

namespace Managing.Infrastructure.Storage
{
    public class CacheService : ICacheService
    {
        private readonly IDistributedCache distributedCache;

        public CacheService(IDistributedCache distributedCache)
        {
            this.distributedCache = distributedCache;
        }

        public string GetValue(string key)
        {
            return distributedCache.GetString(key);
        }

        public T GetValue<T>(string key)
        {
            var cachedData = distributedCache.GetString(key);

            if (!string.IsNullOrEmpty(cachedData))
            {
                return JsonConvert.DeserializeObject<T>(cachedData);
            }

            return default(T);
        }

        public void RemoveValue(string key)
        {
            distributedCache.Remove(key);
        }

        public string SaveValue(string name, string value)
        {
            distributedCache.SetString(name, value);
            return name;
        }

        public void SaveValue<T>(string name, T value, TimeSpan slidingExpiration)
        {
            var options = new DistributedCacheEntryOptions()
            {
                SlidingExpiration = slidingExpiration
            };

            distributedCache.SetString(name, JsonConvert.SerializeObject(value), options);
        }

        public T GetOrSave<T>(string name, Func<T> action, TimeSpan slidingExpiration)
        {
            var cachedData = distributedCache.GetString(name);

            if (!string.IsNullOrEmpty(cachedData))
            {
                return JsonConvert.DeserializeObject<T>(cachedData);
            }

            var options = new DistributedCacheEntryOptions()
            {
                SlidingExpiration = slidingExpiration
            };

            var result = action();

            distributedCache.SetString(name, JsonConvert.SerializeObject(result), options);
            return result;
        }
    }
}