using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;

namespace Harmonia.Core.Caching;

public abstract class MemoryCache<TKey, TValue> : Cache<TKey, TValue> where TKey : notnull
{
    private readonly IMemoryCache _memoryCache;

    protected abstract MemoryCacheOptions Options { get; }
    protected abstract TimeSpan SlidingExpiration { get; }

    public MemoryCache()
    {
        _memoryCache = new MemoryCache(Options);
    }

    protected override TValue? TryGetValue(object key)
    {
        _memoryCache.TryGetValue(key, out TValue? value);

        return value;
    }

    protected override void AddToCache(object key, TValue entry)
    {
        long entrySize = GetEntrySize(entry);

        var cacheEntryOptions = new MemoryCacheEntryOptions()
            .SetSize(entrySize)
            .SetSlidingExpiration(SlidingExpiration)
            .RegisterPostEvictionCallback(PostEvictionCallback);

        _memoryCache.Set(key, entry, cacheEntryOptions);
    }

    protected virtual void PostEvictionCallback(object? cacheKey, object? cacheValue, EvictionReason evictionReason, object? state)
    {

    }

    protected abstract long GetEntrySize(TValue entry);
}