/*
 * Copyright 2018-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"fmt"
	"errors"
	"encoding/json"
	"google.golang.org/grpc"
	"golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
	"github.com/opencord/voltha-lib-go/v2/pkg/log"
	// Values generated by the go template
	{{range .Imports}}
	"{{.}}"
	{{end}}
	{{range .ProtoImports}}
	{{.Short}} "{{.Package}}"
	{{end}}
	// End go template values
)

{{if .Ct}}{{else}}
type clientCtl struct {
	send func(string, context.Context, interface{}, string, metadata.MD) error
	cncl  context.CancelFunc
	ctx context.Context
}
{{end}}

type {{.Name}}ClientConn struct {
	conn * grpc.ClientConn
	control * clientCtl
}


var {{.Name}}Client *{{.Name}}ClientConn


func {{.Name}}Connect() (*{{.Name}}ClientConn, error)  {
	log.Infof("Connecting client {{.Name}} to addr:127.0.0.1, port:{{.Port}}")
	// Dial doesn't block, it just returns and continues connecting in the background.
	// Check back later to confirm and increase the connection count.
	cl := &{{.Name}}ClientConn{control:&clientCtl{}}
	ctx, cnclFnc := context.WithCancel(context.Background())
	cl.control.cncl = cnclFnc
	cl.control.ctx = ctx
	if conn, err := grpc.Dial("127.0.0.1:{{.Port}}", grpc.WithInsecure()); err != nil {
		log.Errorf("Dialng connection :%v",err)
		return nil, err
	} else {
		cl.conn = conn
	}
	{{.Name}}Client = cl
	cl.control.send = {{.Name}}Send
	clients["{{.Name}}"] = cl.control
	return cl, nil
}

// This function will make the requested RPC with the supplied
// parameter and validate that the response matches the expected
// value provided. It will return nil if successful or an error
// if not.
func {{.Name}}Send(mthd string, ctx context.Context, param interface{},
					expect string, expectMeta metadata.MD) error {
	switch mthd {
	{{range .Methods}}
	case "{{.Name}}":
		var hdr metadata.MD
		switch param.(type) {
		case *{{.Param}}:
	{{if .Ss}}
			_=hdr
	{{else if .Cs}}
			_=hdr
	{{else}}
			client := {{.Pkg}}.New{{.Svc}}Client({{$.Name}}Client.conn)
			res, err := client.{{.Name}}(ctx, param.(*{{.Param}}), grpc.Header(&hdr))
			if err != nil {
				return errors.New("Error sending method {{.Name}}")
			}
			// Marshal the result and compare it to the expected
			// value.
			if resS,err := json.Marshal(res); err == nil {
				if string(resS) != expect {
					stats.testLog("Unexpected result returned expected '%s' got '%s'\n", expect, string(resS))
					return errors.New("Unexpected result on method {{.Name}}")
				}
			} else {
				return errors.New("Error Marshaling the reply for method {{.Name}}")
			}
			// Now validate the metadata in the response
			for k,v := range expectMeta {
				if rv,ok := hdr[k]; ok == true {
					if rv[0] != v[0] {
						stats.testLog("Mismatch on returned metadata for key '%s' expected '%s' and got '%s'\n", k, v, rv)
						err = errors.New("Failure on returned metadata")
					}
				} else {
					stats.testLog("Returned metadata missing key '%s'; expected value '%s' at that key\n", k, v)
					err = errors.New("Failure on returned metadata")
				}
			}
			return err
		default:
			return errors.New("Invalid parameter type for method {{.Name}}")
	{{end}}
		}
	{{end}}
		default:
			return errors.New(fmt.Sprintf("Unexpected method %s in send", mthd))
	}
	return nil
}

