package usher

import (
	"bytes"
	"compress/gzip"
	"io"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	"github.com/pkg/errors"
)

type annotations struct {
	singlereply         bool
	extractRequestField string
}

// readAnnotations reads method annotations from the Usher service definition.
func readAnnotations(fileDescriptor []byte, serviceIndex int) (map[string]*annotations, error) {
	ann := make(map[string]*annotations)

	gzipReader, err := gzip.NewReader(bytes.NewReader(fileDescriptor))
	if err != nil {
		return nil, errors.Wrap(err, "ResponseAdapter failed to open gzip reader for file descriptor")
	}

	buf := &bytes.Buffer{}
	if _, err = io.Copy(buf, gzipReader); err != nil {
		return nil, errors.Wrap(err, "ResponseAdapter failed to un-gzip file descriptor")
	}

	usherServiceFd := &descriptor.FileDescriptorProto{}
	if err = proto.Unmarshal(buf.Bytes(), usherServiceFd); err != nil {
		return nil, errors.Wrap(err, "ResponseAdapter failed to unmarshal FileDescriptorProto")
	}

	usherService := usherServiceFd.Service[serviceIndex]
	for _, method := range usherService.Method {
		if method.Options == nil {
			continue
		}

		name := method.GetName()
		a := &annotations{}
		ann[name] = a

		ext, err := proto.GetExtension(method.Options, E_Singlereply)
		if err == nil {
			if singlereply, ok := ext.(*bool); ok && singlereply != nil {
				a.singlereply = *singlereply
			}
		}

		ext, err = proto.GetExtension(method.Options, E_ExtractRequestField)
		if err == nil {
			if extractRequestField, ok := ext.(*string); ok && extractRequestField != nil {
				a.extractRequestField = *extractRequestField
			}
		}
	}

	return ann, nil
}
