/*
 * 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-go/common/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
}

