package util

import (
	"context"
	"time"

	"github.com/eko/gocache/lib/v4/cache"
	"github.com/eko/gocache/lib/v4/codec"
)

// LoadableCacheWithCodec wrap cache.LoadableCache to implement cache.SetterCacheInterface and then make it metrics-able
// The raw cache.LoadableCache ONLY implement cache.CacheInterface not cache.SettlerCacheInterface which is required by cache.MetricCache
// to record metrics.
// So we made this wrapper, in this wrapper, all cache.CacheInterface methods provided by `cache.LoadableCache` and metrics
// are recorded in `cache`. So we can provide the missing methods GetCodec and GetWithTTL by forward call to the `cache`.
type LoadableCacheWithCodec[T any] struct {
	*cache.LoadableCache[T]
	cache *cache.Cache[T]
}

func NewLoadableCacheWithCodec[T any](loadFunc cache.LoadFunction[T], c *cache.Cache[T]) *LoadableCacheWithCodec[T] {
	return &LoadableCacheWithCodec[T]{
		LoadableCache: cache.NewLoadable[T](loadFunc, c),
		cache:         c,
	}
}

func (l *LoadableCacheWithCodec[T]) GetWithTTL(ctx context.Context, key any) (T, time.Duration, error) {
	return l.cache.GetWithTTL(ctx, key)
}

func (l *LoadableCacheWithCodec[T]) GetCodec() codec.CodecInterface {
	return l.cache.GetCodec()
}
