/*
 * 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"
	"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, interface{}, string) 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, param interface{}, expect string) error {
	switch mthd {
	{{range .Methods}}
		case "{{.Name}}":
		switch t := param.(type) {
			case *{{.Param}}:
	{{if .Ss}}
			_=t
	{{else if .Cs}}
			_=t
	{{else}}
			client := {{.Pkg}}.New{{.Svc}}Client({{$.Name}}Client.conn)
			res, err := client.{{.Name}}(context.Background(), t)
			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 {
					return errors.New("Unexpected result on method {{.Name}}")
				}
			} else {
				return errors.New("Error Marshaling the reply for method {{.Name}}")
			}
			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
}

