package ole

import (
	"code.justin.tv/amzn/TwitchOLE/ole/internal/datakeycache"
	telemetry "code.justin.tv/amzn/TwitchTelemetry"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/kms"
)

func (k *KMSClient) getOrGenerateEncryptionDataKey(encryptionContext map[string]string) (plaintext, encrypted []byte, err error) {
	cacheKey := datakeycache.EncryptionKeyCacheCompositeKey{
		EncryptionContext: encryptionContext,
		AlgorithmID:       k.cfg.Algorithm.ID(),
	}

	item := k.encryptionKeyCache.Get(cacheKey)

	return item.GetOrFetchKeys(func() ([]byte, []byte, error) {
		k.reporter.Report("OLECacheEncryptionKeyMiss", 1.0, telemetry.UnitCount)
		output, err := k.kms.GenerateDataKey(&kms.GenerateDataKeyInput{
			EncryptionContext: toAWSEncryptionContext(encryptionContext),
			KeyId:             aws.String(k.cfg.CMKArn),
			KeySpec:           aws.String("AES_256"),
		})
		if err != nil {
			return nil, nil, err
		}

		return output.Plaintext, output.CiphertextBlob, nil
	})
}

func (k *KMSClient) getOrDecryptDecryptionDataKey(cacheKey datakeycache.DecryptionKeyCacheCompositeKey) (plaintext []byte, err error) {
	item := k.decryptionKeyCache.Get(cacheKey)

	plaintext, _, err = item.GetOrFetchKeys(func() ([]byte, []byte, error) {
		k.reporter.Report("OLECacheDecryptionKeyMiss", 1.0, telemetry.UnitCount)
		output, err := k.kms.Decrypt(&kms.DecryptInput{
			CiphertextBlob:    cacheKey.EncryptedDataKey,
			EncryptionContext: toAWSEncryptionContext(cacheKey.EncryptionContext),
		})
		if err != nil {
			return nil, nil, err
		}
		return output.Plaintext, cacheKey.EncryptedDataKey, nil
	})

	return plaintext, err
}
