// Copyright 2017 Michal Witkowski. All Rights Reserved.
// See LICENSE for licensing terms.

package grpc_ctxtags

import (
	"reflect"
)

// RequestFieldExtractorFunc is a user-provided function that extracts field information from a gRPC request.
// It is called from tags middleware on arrival of unary request or a server-stream request.
// Keys and values will be added to the context tags of the request. If there are no fields, you should return a nil.
type RequestFieldExtractorFunc func(fullMethod string, req interface{}) map[string]interface{}

type requestFieldsExtractor interface {
	// ExtractRequestFields is a method declared on a Protobuf message that extracts fields from the interface.
	// The values from the extracted fields should be set in the appendToMap, in order to avoid allocations.
	ExtractRequestFields(appendToMap map[string]interface{})
}

// CodeGenRequestFieldExtractor is a function that relies on code-generated functions that export log fields from requests.
// These are usually coming from a protoc-plugin that generates additional information based on custom field options.
func CodeGenRequestFieldExtractor(fullMethod string, req interface{}) map[string]interface{} {
	if ext, ok := req.(requestFieldsExtractor); ok {
		retMap := make(map[string]interface{})
		ext.ExtractRequestFields(retMap)
		if len(retMap) == 0 {
			return nil
		}
		return retMap
	}
	return nil
}

// TagBasedRequestFieldExtractor is a function that relies on Go struct tags to export log fields from requests.
// These are usually coming from a protoc-plugin, such as Gogo protobuf.
//
//  message Metadata {
//     repeated string tags = 1 [ (gogoproto.moretags) = "log_field:\"meta_tags\"" ];
//  }
//
// The tagName is configurable using the tagName variable. Here it would be "log_field".
func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc {
	return func(fullMethod string, req interface{}) map[string]interface{} {
		retMap := make(map[string]interface{})
		reflectMessageTags(req, retMap, tagName)
		if len(retMap) == 0 {
			return nil
		}
		return retMap
	}
}

func reflectMessageTags(msg interface{}, existingMap map[string]interface{}, tagName string) {
	v := reflect.ValueOf(msg)
	// Only deal with pointers to structs.
	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
		return
	}
	// Deref the pointer get to the struct.
	v = v.Elem()
	t := v.Type()
	for i := 0; i < v.NumField(); i++ {
		field := v.Field(i)
		kind := field.Kind()
		// Only recurse down direct pointers, which should only be to nested structs.
		if kind == reflect.Ptr {
			reflectMessageTags(field.Interface(), existingMap, tagName)
		}
		// In case of arrays/splices (repeated fields) go down to the concrete type.
		if kind == reflect.Array || kind == reflect.Slice {
			if field.Len() == 0 {
				continue
			}
			kind = field.Index(0).Kind()
		}
		// Only be interested in
		if (kind >= reflect.Bool && kind <= reflect.Float64) || kind == reflect.String {
			if tag := t.Field(i).Tag.Get(tagName); tag != "" {
				existingMap[tag] = field.Interface()
			}
		}
	}
	return
}
