// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

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)
}
