/*
 * 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.
 */
// The template for the tester.
// This template is filled in by the
// test driver based on the configuration.

package main

import (
	"fmt"
	"net"
	"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
)

// The channels to get fed the expected results by the test driver.
//var {{.Name}}Meta <-chan string
////var {{.Name}}Payload <-chan string

{{if .Ct}}{{else}}
type reply struct {
	repl interface{}
}
type incoming struct {
	meta metadata.MD
	payload string
}
type  serverCtl struct {
	replyData chan * reply
	incmg chan * incoming
}
{{end}}

type {{.Name}}TestServer struct {
	control *serverCtl
	srv *grpc.Server
}

/*
func init() {
	{{if .Ct}}{{else}}
	if _, err := log.SetDefaultLogger(log.JSON, 0, nil); err != nil {
		log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
	}
	{{end}}
	{{.Name}}ListenAndServe()
}
*/


func {{.Name}}ListenAndServe() error {
	var s {{.Name}}TestServer

	s.control = &serverCtl{replyData:make(chan *reply), incmg:make(chan *incoming)}
	servers["{{.Name}}"] = s.control

	log.Debugf("Starting server %s on port %d", "{{.Name}}", {{.Port}})
	// THe test head always uses localhost 127.0.0.1
	addr := fmt.Sprintf("127.0.0.1:%d", {{.Port}})

	// Create the gRPC server
	s.srv = grpc.NewServer()

{{range .ProtoImports}}
	// Register the handler object
	{{.Short}}.Register{{.Service}}Server(s.srv, s)
{{end}}

	// Create the channel to listen on
	lis, err := net.Listen("tcp", addr)
	if err != nil {
		log.Errorf("could not listen on %s: %s", addr, err)
		return err
	}

	// Serve and Listen
	go func() {
		if err = s.srv.Serve(lis); err != nil {
			log.Errorf("grpc serve error: %s", err)
			return
		}
	}()

	return err
}

{{range .Methods}}
{{if .Ss}}
func (ts {{$.Name}}TestServer) {{.Name}}(in *{{.Param}}, srvr {{.Pkg}}.{{.Svc}}_{{.Name}}Server) error {
	log.Debug("Serving server streaming {{$.Name}}")
	return nil
}
{{else if .Cs}}
func (ts {{$.Name}}TestServer) {{.Name}}({{.Pkg}}.{{.Svc}}_{{.Name}}Server) error {
	log.Debug("Serving client streaming {{$.Name}}")
	return nil
}
{{else}}
func  (ts {{$.Name}}TestServer) {{.Name}}(ctx context.Context, in *{{.Param}}) (*{{.Rtrn}}, error) {
	var r * incoming = &incoming{}
	//log.Debug("Serving {{$.Name}}")
	// Read the metadata
	if md,ok := metadata.FromIncomingContext(ctx); ok == false {
		log.Error("Getting matadata during call to {{.Name}}")
	} else {
		r.meta = md.Copy()
	}
	// Read the data sent to the function
	if parm,err := json.Marshal(in); err != nil {
		log.Error("Marshalling the {{.Param}} for {{.Name}}")
	} else {
		r.payload = string(parm)
	}
	// Send the server information back to the test framework
	go func(ctx context.Context) {
		select {
		case ts.control.incmg <- r:
			return
		case <-ctx.Done():
			return

		}
	}(glCtx)
	// Read the value that needs to be returned from the channel
	select {
	case d := <-ts.control.replyData:
		switch r := d.repl.(type) {
			case *{{.Rtrn}}:
				return r, nil
			default:
				return nil, errors.New("Mismatched type in call to {{.Name}}")
		}
	case <-glCtx.Done():
		return nil, errors.New("Timeout: nothing in the reply data channel in call to {{.Name}}, sending nil")
	}
	return &{{.Rtrn}}{},nil
}
{{end}}
{{end}}

