using Microsoft.Extensions.Caching.Memory;
using Kit.Helpers.Cache;
using Kit.Helpers.Repository.Xml;
using System;
using System.Collections.Generic;

namespace Kit.Helpers.Repository
{
    public interface IDictionaryRepository<TKey, TEntity>
    {
        IDictionary<TKey, TEntity> Select();
        TEntity Get(TKey key);
        void ClearCache();
    }


    public abstract class DictionaryRepository<TKey, TEntity> : IDictionaryRepository<TKey, TEntity>
        where TEntity : IPersistentKey<TKey>
    {
        private string _cacheKey;
        private ICacheProvider _cacheProvider;
        public DictionaryRepository(ICacheProvider cacheProvider, string cacheKey)
        {
            _cacheProvider = cacheProvider;
            _cacheKey = cacheKey;
        }

        // лучше сделать абстрактным
        protected abstract IEnumerable<TEntity> GetData();

        public IDictionary<TKey, TEntity> Select()
        {
            IDictionary<TKey, TEntity> values;
            if (_cacheKey.IsNullOrEmpty())
            {
                throw new ArgumentNullException("Не задан ключ кеширования для репозитория: {0}".ApplyFormat(this.GetType().ToString()));
            }

            if (_cacheProvider.Contains(_cacheKey))
            {
                values = _cacheProvider.GetCacheData<IDictionary<TKey, TEntity>>(_cacheKey);
            }
            else
            {

                IEnumerable<TEntity> data = this.GetData();
                values = new Dictionary<TKey, TEntity>();
                // добавить обработку дубликатов
                foreach (var item in data)
                {
                    TKey key = item.PersistentKey;
                    if (values.ContainsKey(key))
                    {
                        throw new Exception("Элемент с ключом {0} уже добавлен в коллекцию".ApplyFormat(key));
                    }
                    values.Add(item.PersistentKey, item);
                }

                _cacheProvider.SetCacheData(_cacheKey, values,
                    new MemoryCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1),
                        Priority = CacheItemPriority.Normal
                    });
            }
            return values;
        }
        public TEntity Get(TKey key)
        {
            IDictionary<TKey, TEntity> values = this.Select();
            if (values.ContainsKey(key))
                return values[key];
            else
                return default(TEntity);
        }

        public void ClearCache()
        {
            _cacheProvider.PurgeCacheItems(_cacheKey);
        }
    }
}