package getproviders

import (
	"context"
	"sync"

	"github.com/hashicorp/terraform/internal/addrs"
)

// MemoizeSource is a Source that wraps another Source and remembers its
// results so that they can be returned more quickly on future calls to the
// same object.
//
// Each MemoizeSource maintains a cache of response it has seen as part of its
// body. All responses are retained for the remaining lifetime of the object.
// Errors from the underlying source are also cached, and so subsequent calls
// with the same arguments will always produce the same errors.
//
// A MemoizeSource can be called concurrently, with incoming requests processed
// sequentially.
type MemoizeSource struct {
	underlying        Source
	availableVersions map[addrs.Provider]memoizeAvailableVersionsRet
	packageMetas      map[memoizePackageMetaCall]memoizePackageMetaRet
	mu                sync.Mutex
}

type memoizeAvailableVersionsRet struct {
	VersionList VersionList
	Warnings    Warnings
	Err         error
}

type memoizePackageMetaCall struct {
	Provider addrs.Provider
	Version  Version
	Target   Platform
}

type memoizePackageMetaRet struct {
	PackageMeta PackageMeta
	Err         error
}

var _ Source = (*MemoizeSource)(nil)

// NewMemoizeSource constructs and returns a new MemoizeSource that wraps
// the given underlying source and memoizes its results.
func NewMemoizeSource(underlying Source) *MemoizeSource {
	return &MemoizeSource{
		underlying:        underlying,
		availableVersions: make(map[addrs.Provider]memoizeAvailableVersionsRet),
		packageMetas:      make(map[memoizePackageMetaCall]memoizePackageMetaRet),
	}
}

// AvailableVersions requests the available versions from the underlying source
// and caches them before returning them, or on subsequent calls returns the
// result directly from the cache.
func (s *MemoizeSource) AvailableVersions(ctx context.Context, provider addrs.Provider) (VersionList, Warnings, error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	if existing, exists := s.availableVersions[provider]; exists {
		return existing.VersionList, nil, existing.Err
	}

	ret, warnings, err := s.underlying.AvailableVersions(ctx, provider)
	s.availableVersions[provider] = memoizeAvailableVersionsRet{
		VersionList: ret,
		Err:         err,
		Warnings:    warnings,
	}
	return ret, warnings, err
}

// PackageMeta requests package metadata from the underlying source and caches
// the result before returning it, or on subsequent calls returns the result
// directly from the cache.
func (s *MemoizeSource) PackageMeta(ctx context.Context, provider addrs.Provider, version Version, target Platform) (PackageMeta, error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	key := memoizePackageMetaCall{
		Provider: provider,
		Version:  version,
		Target:   target,
	}
	if existing, exists := s.packageMetas[key]; exists {
		return existing.PackageMeta, existing.Err
	}

	ret, err := s.underlying.PackageMeta(ctx, provider, version, target)
	s.packageMetas[key] = memoizePackageMetaRet{
		PackageMeta: ret,
		Err:         err,
	}
	return ret, err
}

func (s *MemoizeSource) ForDisplay(provider addrs.Provider) string {
	return s.underlying.ForDisplay(provider)
}
