package {{.File.Package}}_grpctransport

{{$file := .File}}

import (
	context "context"
        "fmt"

        oldcontext "golang.org/x/net/context"
	grpctransport "github.com/go-kit/kit/transport/grpc"

        pb "{{cat .GoPWD "/" .DestinationDir | nospace | clean}}/pb"
        endpoints "{{cat .GoPWD "/" .DestinationDir | nospace | clean}}/endpoints"
)

// avoid import errors
var _ = fmt.Errorf

func MakeGRPCServer(endpoints endpoints.Endpoints) pb.{{.File.Package | title}}ServiceServer {
     	var options []grpctransport.ServerOption
        _ = options
	return &grpcServer{
		{{range .Service.Method}}
			{{if or (.ClientStreaming) (.ServerStreaming)}}
				{{.Name | lower}}: &server{
					e: endpoints.{{.Name}}Endpoint,
				},
			{{else}}
				{{.Name | lower}}: grpctransport.NewServer(
					endpoints.{{.Name}}Endpoint,
					decodeRequest,
					encode{{.Name}}Response,
					options...,
				),
			{{end}}
                {{end}}
	}
}

type grpcServer struct {
	{{range .Service.Method}}
		{{if or (.ClientStreaming) (.ServerStreaming)}}
			{{.Name | lower}} streamHandler
		{{else}}
			{{.Name | lower}} grpctransport.Handler
		{{end}}
	{{end}}
}

{{range .Service.Method}}
	{{if .ClientStreaming}}
		func (s *grpcServer) {{.Name}}(server pb.{{$file.Package | title}}Service_{{.Name}}Server) error {
		        return s.{{.Name | lower}}.Do(server, nil)
		}
	{{else if .ServerStreaming}}
		func (s *grpcServer) {{.Name}}(req *pb.{{.Name}}Request, server pb.{{$file.Package | title}}Service_{{.Name}}Server) error {
		        return s.{{.Name | lower}}.Do(server, req)
		}
	{{else}}
		func (s *grpcServer) {{.Name}}(ctx oldcontext.Context, req *pb.{{.InputType | splitArray "." | last}}) (*pb.{{.OutputType | splitArray "." | last}}, error) {
		_, rep, err := s.{{.Name | lower}}.ServeGRPC(ctx, req)
			if err != nil {
				return nil, err
			}
			return rep.(*pb.{{.OutputType | splitArray "." | last}}), nil
		}

		func encode{{.Name}}Response(ctx context.Context, response interface{}) (interface{}, error) {
			resp := response.(*pb.{{.OutputType | splitArray "." | last}})
			return resp, nil
		}
	{{end}}
{{end}}

func decodeRequest(ctx context.Context, grpcReq interface{}) (interface{}, error) {
	return grpcReq, nil
}

type streamHandler interface{
	Do(server interface{}, req interface{}) (err error)
}

type server struct {
	e endpoints.StreamEndpoint
}

func (s server) Do(server interface{}, req interface{}) (err error) {
	if err := s.e(server, req); err != nil {
		return err
	}
	return nil
}
