func checkMeasMatchInSwIDList(swidList []SoftwareIdentity, meas string) (SoftwareIdentity, bool) {
	var locSwID SoftwareIdentity
	for _, swid := range swidList {
		if swid.Payload[FirstIndex].Resources[FirstIndex].MeasurementValue == meas {
			return swid, true
		}
	}
	return locSwID, false
}
checkMeasMatchInSwIDList is a utility function which checks for
given measurement to be present in the SWID List
package main
import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"github.com/hashicorp/go-plugin"
	"github.com/veraison/common"
)
const (
	HW = "HW"
	SW = "SW"
	Edge = "Edge"
	Rel = "Rel"
)
const (
	mindepth      = "1"
	maxdepth      = "10"
	to            = ".."
	space         = " "
	newline       = "\n"
	filterPatches = "FILTER link.rel == 'patches' "
	filterUpdates = "FILTER link.rel == 'updates' "
)
type EndorsementStore struct {
	common.BaseEndorsementStore
	store Store
}
type Resource struct {
	Type             string `json:"type"`
	MeasType         string `json:"arm.com-PSAMeasurementType"`
	Description      string `json:"arm.com-PSADescription"`
	MeasurementValue string `json:"arm.com-PSAMeasurementValue"`
	SignerID         string `json:"arm.com-PSASignerId"`
}
type ResourceCollection struct {
	Resources []Resource `json:"resource"`
}
type PsaEntity struct {
	Name  string   `json:"entity-name"`
	RegID string   `json:"reg-id"`
	Role  []string `json:"role"`
}
type PsaHardwareRot struct {
	ImplementationID string `json:"implementation-id"`
	HwVer            string `json:"hw-ver"`
}
type SoftwareIdentity struct {
	TagID           string               `json:"tag-id"`
	TagVersion      int                  `json:"tag-version"`
	SoftwareName    string               `json:"software-name"`
	SoftwareVersion string               `json:"software-version"`
	Entity          []PsaEntity          `json:"entity"`
	Payload         []ResourceCollection `json:"payload"`
}
type HardwareIdentity struct {
	TagID       string         `json:"tag-id"`
	Entity      []PsaEntity    `json:"entity"`
	HardwareRot PsaHardwareRot `json:"psa-hardware-rot"`
}
type HardwareIdentityWrapper struct {
	ID      HardwareIdentity `json:"HardwareIdentity"`
	RawData json.RawMessage
}
type SoftwareIdentityWrapper struct {
	ID      SoftwareIdentity `json:"SoftwareIdentity"`
	Rawdata json.RawMessage
}
const FirstIndex = 0
func (e *EndorsementStore) GetName() string {
	return "arangodb"
}
func (e *EndorsementStore) Init(args common.EndorsementStoreParams) error {
	e.Queries = map[string]common.Query{
		"hardware_id":           e.GetHardwareID,
		"software_components":   e.GetSoftwareComponents,           
		"all_sw_components":     e.GetAllSoftwareComponents,        
		"linked_sw_comp_latest": e.GetMostRecentSwVerOfLinkedComp,  
		"sw_component_latest":   e.GetMostRecentSwVerOfAnySWComp,   
	}
	_, found := args["AltAlgorithm"]
	if found {
		e.Queries["software_components"] = e.GetAltSoftwareComponents
	}
	store, found := args["storeInstance"]
	if !found {
		return fmt.Errorf("DB store instance is not provided inside FetcherParams")
	}
	e.store = store.(Store)
	if !e.store.IsInitialised() {
		return fmt.Errorf("uninitialized DB store provided in FetcherParams")
	}
	ctx := context.Background()
	if err := e.store.Connect(ctx); err != nil {
		return fmt.Errorf("DB connection failed: %w", err)
	}
	return nil
}
func (e *EndorsementStore) Close() error {
	ctx := context.Background()
	if err := e.store.Connect(ctx); err != nil {
		return err
	}
	if err := e.store.Close(ctx); err != nil {
		return err
	}
	return nil
}
func (e *EndorsementStore) GetHwIDFromDB(platformID string, hwID *HardwareIdentity) error {
	var hardwareInstance HardwareIdentityWrapper
	ctx := context.Background()
	if err := e.store.Connect(ctx); err != nil {
		return err
	}
	queryArgs := map[string]interface{}{
		"platformId": platformID,
	}
	hwCollection, _ := e.store.GetQueryParam(HW)
	query := "FOR d IN " + hwCollection
	query += " FILTER d.HardwareIdentity.`psa-hardware-rot`.`implementation-id` == @platformId RETURN d"
	log.Printf("input query = %s", query)
	resultList, err := e.store.RunQuery(ctx, query, queryArgs, &hardwareInstance)
	if err != nil {
		return fmt.Errorf("query failed: %w", err)
	}
	for _, resultValue := range resultList {
		hardwareInstance = resultValue.(HardwareIdentityWrapper)
		break
	}
	*hwID = hardwareInstance.ID
	return nil
}
func (e *EndorsementStore) GetSwIDTagsLinkedToHWTagFromDB(hwTag string) ([]SoftwareIdentity, error) {
	hwCollection, _ := e.store.GetQueryParam(HW)
	hwColTag := hwCollection + "/" + hwTag
	hwColTag = "'" + hwColTag + "'"
	edgeCollection, _ := e.store.GetQueryParam(Edge)
	query := "FOR swid, link IN INBOUND " + hwColTag + space + edgeCollection
	query += newline + " FILTER link.rel == 'psa-rot-compound' RETURN swid"
	swidList, err := e.GetSwIDTagsForQueryFromDB(query)
	if err != nil {
		return nil, fmt.Errorf("query GetSwIDTagsForQueryFromDB failed: %w", err)
	}
	return swidList, nil
}
func (e *EndorsementStore) GetHardwareID(args common.QueryArgs) (common.QueryResult, error) {
	var platformID string
	var result []interface{}
	var hwID HardwareIdentity
	hwMap := make(map[string]string)
	platformID, err := ExtractPlatformID(args)
	if err != nil {
		return nil, fmt.Errorf("failed to extract platform_id from query params: %w", err)
	}
	err = e.GetHwIDFromDB(platformID, &hwID)
	if err != nil {
		return nil, fmt.Errorf("for given platform id=%s, failed to fetch the hwID from DB: %w", platformID, err)
	}
	hwMap["hw_id"] = hwID.HardwareRot.HwVer
	result = append(result, hwMap["hw_id"])
	return result, nil
}
func IsMeasurementInList(measure string, measurements []string) (bool, error) {
	IsPresent := false
	if measure == "" {
		return IsPresent, fmt.Errorf("invalid input NULL measurement")
	}
	if len(measurements) == 0 {
		return IsPresent, fmt.Errorf("invalid query measurement arguments, no measurements present")
	}
	for _, measureValue := range measurements {
		if measure == measureValue {
			IsPresent = true
			break
		}
	}
	return IsPresent, nil
}
func ExtractPlatformID(args common.QueryArgs) (string, error) {
	var platformID string
	platformIDArg, ok := args["platform_id"]
	if !ok {
		return platformID, fmt.Errorf("missing mandatory query argument 'platform_id'")
	}
	switch v := platformIDArg.(type) {
	case string:
		platformID = v
	case []interface{}:
		platformID, ok = v[0].(string)
		if !ok {
			return platformID, fmt.Errorf("unexpected type for 'platform_id'; must be a string")
		}
	default:
		return platformID, fmt.Errorf("unexpected type for 'platform_id'; must be a string; found: %T", v)
	}
	return platformID, nil
}
func ExtractSoftwareComponents(args common.QueryArgs) ([]string, error) {
	var measurements []string
	measurementsArg, ok := args["measurements"]
	if !ok {
		return nil, fmt.Errorf("missing mandatory query argument 'measurements'")
	}
	switch v := measurementsArg.(type) {
	case []interface{}:
		for _, elt := range v {
			measure, ok := elt.(string)
			if !ok {
				return nil, fmt.Errorf("unexpected type for 'measurements'; must be a []string")
			}
			measurements = append(measurements, measure)
		}
	case []string:
		measurements = v
	default:
		return nil, fmt.Errorf("unexpected type for 'measurements'; must be []string, found: %T", v)
	}
	return measurements, nil
}
func (e *EndorsementStore) GetSoftwareComponents(args common.QueryArgs) (common.QueryResult, error) {
	var platformID string
	var result []interface{}
	var finalList [][]SoftwareIdentity
	var schemeEndorsements []map[string]string
	matched := false
	platformID, err := ExtractPlatformID(args)
	if err != nil {
		return nil, fmt.Errorf("failed to extract platform_id from query params: %w", err)
	}
	measurements, err := ExtractSoftwareComponents(args)
	if err != nil {
		return nil, fmt.Errorf("failed to extract software components from query params: %w", err)
	}
	if len(measurements) == 0 {
		return common.QueryResult{[]interface{}{}}, nil
	}
	finalList, err = e.GetAllswidForPlatform(platformID)
	if err != nil {
		return nil, fmt.Errorf("failed to extract swIDs for platform Id=%s %w", platformID, err)
	}
	for _, swidList := range finalList {
		matched = false
		for _, swid := range swidList {
			log.Printf("got SWID with tag = %s", swid.TagID)
			swMeasurement := swid.Payload[FirstIndex].Resources[FirstIndex].MeasurementValue
			matched, err = IsMeasurementInList(swMeasurement, measurements)
			if err != nil {
				return nil, fmt.Errorf("error happened while matching measurements: %w ", err)
			}
			if matched {
				swMap := map[string]string{
					"measurement":          swMeasurement,
					"sw_component_type":    swid.Payload[FirstIndex].Resources[FirstIndex].MeasType,
					"sw_component_version": swid.SoftwareVersion,
					"signer_id":            swid.Payload[FirstIndex].Resources[FirstIndex].SignerID,
				}
				schemeEndorsements = append(schemeEndorsements, swMap)
				break
			}
		}
		if !matched {
			log.Printf("no matched component for platform linked swid = %s", swidList[FirstIndex].TagID)
			break
		}
	}
	if !matched {
		return nil, fmt.Errorf("no matched component for platform linked swid")
	}
	result = append(result, schemeEndorsements)
	return result, nil
}
func (e *EndorsementStore) GetAltSoftwareComponents(args common.QueryArgs) (common.QueryResult, error) {
	var platformID string
	var result []interface{}
	var swidList []SoftwareIdentity
	var schemeEndorsements []map[string]string
	var hwID HardwareIdentity
	platformID, err := ExtractPlatformID(args)
	if err != nil {
		return nil, fmt.Errorf("failed to extract platform_id from query params: %w", err)
	}
	measurements, err := ExtractSoftwareComponents(args)
	if err != nil {
		return nil, fmt.Errorf("failed to extract software components from query params: %w", err)
	}
	if len(measurements) == 0 {
		return common.QueryResult{[]interface{}{}}, nil
	}
	err = e.GetHwIDFromDB(platformID, &hwID)
	if err != nil {
		return nil, fmt.Errorf("for given platform id=%s, failed to fetch the hwID from DB: %w", platformID, err)
	}
	hwTag := hwID.TagID
	swidList, err = e.GetSwIDTagsLinkedToHWTagFromDB(hwTag)
	if err != nil {
		return nil, fmt.Errorf("query GetAllSoftwareComponents failed: %w", err)
	}
	var unmatchedSwid []SoftwareIdentity
	for _, swid := range swidList {
		log.Printf("got SWID with tag = %s", swid.TagID)
		swMeasurement := swid.Payload[FirstIndex].Resources[FirstIndex].MeasurementValue
		matched, err := IsMeasurementInList(swMeasurement, measurements)
		if err != nil {
			return nil, fmt.Errorf("error happened while matching measurements: %w ", err)
		}
		if matched {
			swMap := map[string]string{
				"measurement":          swMeasurement,
				"sw_component_type":    swid.Payload[FirstIndex].Resources[FirstIndex].MeasType,
				"sw_component_version": swid.SoftwareVersion,
				"signer_id":            swid.Payload[FirstIndex].Resources[FirstIndex].SignerID,
			}
			schemeEndorsements = append(schemeEndorsements, swMap)
		} else {
			unmatchedSwid = append(unmatchedSwid, swid)
		}
	}
	for _, swid := range unmatchedSwid {
		log.Printf("umatched SWID = %s", swid.TagID)
		relList, err := e.GetAllSwRelForBaseTag(swid.TagID)
		if err != nil {
			return nil, fmt.Errorf("error occurred while fetching relations: %w", err)
		}
		for _, relswid := range relList {
			log.Printf("got linked SWID with tag = %s", relswid.TagID)
			swMeasurement := relswid.Payload[FirstIndex].Resources[FirstIndex].MeasurementValue
			matched, err := IsMeasurementInList(swMeasurement, measurements)
			if err != nil {
				return nil, fmt.Errorf("error happened while matching measurements: %w", err)
			}
			if matched {
				swMap := map[string]string{
					"measurement":          swMeasurement,
					"sw_component_type":    relswid.Payload[FirstIndex].Resources[FirstIndex].MeasType,
					"sw_component_version": relswid.SoftwareVersion,
					"signer_id":            relswid.Payload[FirstIndex].Resources[FirstIndex].SignerID,
				}
				schemeEndorsements = append(schemeEndorsements, swMap)
			}
		}
	}
	result = append(result, schemeEndorsements)
	return result, nil
}
func (e *EndorsementStore) GetSwIDTagsForQueryFromDB(query string) ([]SoftwareIdentity, error) {
	var swidList []SoftwareIdentity
	var swDocWrap SoftwareIdentityWrapper
	ctx := context.Background()
	if err := e.store.Connect(ctx); err != nil {
		return nil, err
	}
	log.Printf("supplied query = %s", query)
	swDocWrapList, err := e.store.RunQuery(ctx, query, nil, &swDocWrap)
	if err != nil {
		return nil, fmt.Errorf("query failed to fetch swIDs: %w", err)
	}
	for _, swDocWrap := range swDocWrapList {
		softwareInstance := swDocWrap.(SoftwareIdentityWrapper)
		swidList = append(swidList, softwareInstance.ID)
	}
	return swidList, nil
}
func (e *EndorsementStore) GetAllSoftwareComponents(args common.QueryArgs) (common.QueryResult, error) {
	var platformID string
	var result []interface{}
	var finalList [][]SoftwareIdentity
	var schemeEndorsements []map[string]string
	platformID, err := ExtractPlatformID(args)
	if err != nil {
		return nil, fmt.Errorf("failed to extract platform_id from query params: %w", err)
	}
	finalList, err = e.GetAllswidForPlatform(platformID)
	if err != nil {
		return nil, fmt.Errorf("failed to extract swid list for a platform Id=%s %w", platformID, err)
	}
	for _, swidList := range finalList {
		for _, swid := range swidList {
			log.Printf("fetched SWID = %s", swid.TagID)
			swMeasurement := swid.Payload[FirstIndex].Resources[FirstIndex].MeasurementValue
			swMap := map[string]string{
				"measurement":          swMeasurement,
				"sw_component_type":    swid.Payload[FirstIndex].Resources[FirstIndex].MeasType,
				"sw_component_version": swid.SoftwareVersion,
				"signer_id":            swid.Payload[FirstIndex].Resources[FirstIndex].SignerID,
			}
			schemeEndorsements = append(schemeEndorsements, swMap)
		}
	}
	result = append(result, schemeEndorsements)
	return result, nil
}
func (e *EndorsementStore) GetAllswidForPlatform(platformID string) ([][]SoftwareIdentity, error) {
	var hwID HardwareIdentity
	var finalList [][]SoftwareIdentity
	err := e.GetHwIDFromDB(platformID, &hwID)
	if err != nil {
		return nil, fmt.Errorf("for given platform id=%s, failed to fetch the hwID from DB: %w", platformID, err)
	}
	hwTag := hwID.TagID
	swidList, err := e.GetSwIDTagsLinkedToHWTagFromDB(hwTag)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch swIDs linked to hwTag=%s reason: %w", hwTag, err)
	}
	for _, swid := range swidList {
		log.Printf("fetched SWID = %s", swid.TagID)
		var indexSwidList []SoftwareIdentity
		indexSwidList = append(indexSwidList, swid)
		relList, err := e.GetAllSwRelForBaseTag(swid.TagID)
		if err != nil {
			return nil, fmt.Errorf("could not fetch all sw relations for base sw tag=%s: %w", swid.TagID, err)
		}
		indexSwidList = append(indexSwidList, relList...)
		finalList = append(finalList, indexSwidList)
	}
	return finalList, nil
}
func (e *EndorsementStore) GetAllSwRelForBaseTag(swIDTag string) ([]SoftwareIdentity, error) {
	var swidList []SoftwareIdentity
	swCollection, _ := e.store.GetQueryParam(SW)
	swColTag := swCollection + "/" + swIDTag
	swColTag = "'" + swColTag + "'"
	query := "FOR swid IN " + mindepth + to + maxdepth + " ANY " + swColTag + space
	relCollection, _ := e.store.GetQueryParam(Rel)
	query += relCollection + newline + " RETURN swid"
	log.Printf("constructed query = %s", query)
	swidList, err := e.GetSwIDTagsForQueryFromDB(query)
	if err != nil {
		return nil, fmt.Errorf("query GetAllSwRelForBaseTag=%s failed: %w", query, err)
	}
	return swidList, nil
}
func (e *EndorsementStore) GetAllSwPatchesForSwIDTag(swIDTag string) ([]SoftwareIdentity, error) {
	var swidList []SoftwareIdentity
	swCollection, _ := e.store.GetQueryParam(SW)
	relCollection, _ := e.store.GetQueryParam(Rel)
	swColTag := swCollection + "/" + swIDTag
	swColTag = "'" + swColTag + "'"
	query := "FOR swid, link IN " + mindepth + to + maxdepth + " ANY " + swColTag + space
	query += relCollection + newline + filterPatches + "RETURN swid"
	log.Printf("constructed query = %s", query)
	swidList, err := e.GetSwIDTagsForQueryFromDB(query)
	if err != nil {
		return nil, fmt.Errorf("query GetAllSwPatchesForSwIDTag=%s failed: %w", query, err)
	}
	return swidList, nil
}
func (e *EndorsementStore) GetAllSwUpdatesForSwIDTag(swIDTag string) ([]SoftwareIdentity, error) {
	var swidList []SoftwareIdentity
	swCollection, _ := e.store.GetQueryParam(SW)
	swColTag := swCollection + "/" + swIDTag
	swColTag = "'" + swColTag + "'"
	relCollection, _ := e.store.GetQueryParam(Rel)
	query := "FOR swid, link IN " + mindepth + to + maxdepth + " ANY " + swColTag + space
	query += relCollection + newline + filterUpdates + "RETURN swid"
	log.Printf("constructed query = %s", query)
	swidList, err := e.GetSwIDTagsForQueryFromDB(query)
	if err != nil {
		return nil, fmt.Errorf("query GetAllSwUpdatesForSwIDTag=%s failed: %w", query, err)
	}
	return swidList, nil
}
func (e *EndorsementStore) GetPatchListForBaseSwVersion(SwTag string) ([]SoftwareIdentity, error) {
	swCollection, _ := e.store.GetQueryParam(SW)
	relCollection, _ := e.store.GetQueryParam(Rel)
	swColTag := swCollection + "/" + SwTag
	swColTag = "'" + swColTag + "'"
	query := "FOR swid, link IN " + mindepth + to + maxdepth + " INBOUND "
	query += swColTag + space + relCollection + newline
	query += "PRUNE link.rel == 'updates'" + newline
	query += filterPatches + "RETURN swid"
	log.Printf("Constructed Query = %s", query)
	PatchList, err := e.GetSwIDTagsForQueryFromDB(query)
	if err != nil {
		return nil, fmt.Errorf("query GetPatchListForBaseSwVersion=%s failed: %w", query, err)
	}
	return PatchList, nil
}
func (e *EndorsementStore) GetBaseSwVersionFromPatch(Patchswid SoftwareIdentity) (SoftwareIdentity, error) {
	var baseswid SoftwareIdentity
	var swidList []SoftwareIdentity
	swCollection, _ := e.store.GetQueryParam(SW)
	relCollection, _ := e.store.GetQueryParam(Rel)
	swColTag := swCollection + "/" + Patchswid.TagID
	swColTag = "'" + swColTag + "'"
	query := "FOR swid, link IN " + mindepth + to + maxdepth + " OUTBOUND "
	query += swColTag + space + relCollection + newline
	query += "PRUNE link.rel == 'updates'" + newline
	query += filterPatches + "RETURN swid"
	log.Printf("constructed query = %s", query)
	swidList, err := e.GetSwIDTagsForQueryFromDB(query)
	if err != nil {
		return baseswid, fmt.Errorf("query GetBaseSwVersionFromPatch=%s failed: %w", query, err)
	}
	if len(swidList) == 0 {
		return Patchswid, nil
	}
	baseswid = swidList[len(swidList)-1]
	return baseswid, nil
}
func (e *EndorsementStore) GetUpdatesListForBaseSwVersion(Baseswid SoftwareIdentity) ([]SoftwareIdentity, error) {
	swCollection, _ := e.store.GetQueryParam(SW)
	relCollection, _ := e.store.GetQueryParam(Rel)
	swColTag := swCollection + "/" + Baseswid.TagID
	swColTag = "'" + swColTag + "'"
	query := "FOR swid, link IN " + mindepth + to + maxdepth + " INBOUND "
	query += swColTag + space + relCollection + newline
	query += "PRUNE link.rel == 'patches'" + newline
	query += filterUpdates + "RETURN swid"
	log.Printf("constructed query = %s", query)
	UpdateList, err := e.GetSwIDTagsForQueryFromDB(query)
	if err != nil {
		return nil, fmt.Errorf("query GetUpdatesListForBaseSwVersion=%s failed: %w", query, err)
	}
	if len(UpdateList) == 0 {
		UpdateList = append(UpdateList, Baseswid)
	}
	return UpdateList, nil
}
func (e *EndorsementStore) GetMostRecentSwVerOfLinkedComp(args common.QueryArgs) (common.QueryResult, error) {
	var platformID string
	var measurements []string
	var result []interface{}
	var schemeEndorsements []map[string]string
	var swidList []SoftwareIdentity
	var hwID HardwareIdentity
	platformID, err := ExtractPlatformID(args)
	if err != nil {
		return nil, fmt.Errorf("failed to extract platform_id from query params: %w", err)
	}
	measurements, err = ExtractSoftwareComponents(args)
	if err != nil {
		return nil, fmt.Errorf("failed to extract software components from query params: %w", err)
	}
	if len(measurements) == 0 {
		return common.QueryResult{[]interface{}{}}, nil
	}
	err = e.GetHwIDFromDB(platformID, &hwID)
	if err != nil {
		return nil, fmt.Errorf("for given platform id=%s, failed to fetch the hwID from DB %w", platformID, err)
	}
	hwTag := hwID.TagID
	swidList, err = e.GetSwIDTagsLinkedToHWTagFromDB(hwTag)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch swid list for hwTag=%s,  %w", hwTag, err)
	}
	meas := measurements[0]
	requiredswid, matched := checkMeasMatchInSwIDList(swidList, meas)
	if !matched {
		return nil, fmt.Errorf("query failed platform identity=%s, has no matching measurements", platformID)
	}
	latestSwid := requiredswid
	updateList, err := e.GetUpdatesListForBaseSwVersion(latestSwid)
	if err != nil {
		return nil, fmt.Errorf("query failed as unable to fetch update list for base sw version tag %s, %w", latestSwid.TagID, err)
	}
	if (len(updateList)) != 0 {
		latestSwid = updateList[len(updateList)-1]
	}
	patchList, err := e.GetPatchListForBaseSwVersion(latestSwid.TagID)
	if err != nil {
		return nil, fmt.Errorf("query failed as unable to fetch patch list for base sw version tag %s, %w", latestSwid.TagID, err)
	}
	if (len(patchList)) != 0 {
		latestSwid = patchList[len(patchList)-1]
	}
	swMeasurement := latestSwid.Payload[FirstIndex].Resources[FirstIndex].MeasurementValue
	swMap := map[string]string{
		"measurement":          swMeasurement,
		"sw_component_type":    latestSwid.Payload[FirstIndex].Resources[FirstIndex].MeasType,
		"sw_component_version": latestSwid.SoftwareVersion,
		"signer_id":            latestSwid.Payload[FirstIndex].Resources[FirstIndex].SignerID,
	}
	schemeEndorsements = append(schemeEndorsements, swMap)
	result = append(result, schemeEndorsements)
	return result, nil
}