// Code generated by go generate; DO NOT EDIT.
// 2021-09-05 13:54:19.664951 +0200 CEST m=+0.000206417

package ooapi

//go:generate go run ./internal/generator -file caching.go

import (
	"context"
	"reflect"

	"github.com/ooni/probe-cli/v3/internal/ooapi/apimodel"
)

// withCacheMeasurementMetaAPI implements caching for simpleMeasurementMetaAPI.
type withCacheMeasurementMetaAPI struct {
	API      callerForMeasurementMetaAPI // mandatory
	GobCodec GobCodec                    // optional
	KVStore  KVStore                     // mandatory
}

type cacheEntryForMeasurementMetaAPI struct {
	Req  *apimodel.MeasurementMetaRequest
	Resp *apimodel.MeasurementMetaResponse
}

// Call calls the API and implements caching.
func (c *withCacheMeasurementMetaAPI) Call(ctx context.Context, req *apimodel.MeasurementMetaRequest) (*apimodel.MeasurementMetaResponse, error) {
	if resp, _ := c.readcache(req); resp != nil {
		return resp, nil
	}
	resp, err := c.API.Call(ctx, req)
	if err != nil {
		return nil, err
	}
	if err := c.writecache(req, resp); err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *withCacheMeasurementMetaAPI) gobCodec() GobCodec {
	if c.GobCodec != nil {
		return c.GobCodec
	}
	return &defaultGobCodec{}
}

func (c *withCacheMeasurementMetaAPI) getcache() ([]cacheEntryForMeasurementMetaAPI, error) {
	data, err := c.KVStore.Get("MeasurementMeta.cache")
	if err != nil {
		return nil, err
	}
	var out []cacheEntryForMeasurementMetaAPI
	if err := c.gobCodec().Decode(data, &out); err != nil {
		return nil, err
	}
	return out, nil
}

func (c *withCacheMeasurementMetaAPI) setcache(in []cacheEntryForMeasurementMetaAPI) error {
	data, err := c.gobCodec().Encode(in)
	if err != nil {
		return err
	}
	return c.KVStore.Set("MeasurementMeta.cache", data)
}

func (c *withCacheMeasurementMetaAPI) readcache(req *apimodel.MeasurementMetaRequest) (*apimodel.MeasurementMetaResponse, error) {
	cache, err := c.getcache()
	if err != nil {
		return nil, err
	}
	for _, cur := range cache {
		if reflect.DeepEqual(req, cur.Req) {
			return cur.Resp, nil
		}
	}
	return nil, errCacheNotFound
}

func (c *withCacheMeasurementMetaAPI) writecache(req *apimodel.MeasurementMetaRequest, resp *apimodel.MeasurementMetaResponse) error {
	cache, _ := c.getcache()
	out := []cacheEntryForMeasurementMetaAPI{{Req: req, Resp: resp}}
	const toomany = 64
	for idx, cur := range cache {
		if reflect.DeepEqual(req, cur.Req) {
			continue // we already updated the cache
		}
		if idx > toomany {
			break
		}
		out = append(out, cur)
	}
	return c.setcache(out)
}

var _ callerForMeasurementMetaAPI = &withCacheMeasurementMetaAPI{}
