// This file was auto-generated by the veyron vdl tool.
// Source: wire.vdl

package main

import (
	// The non-user imports are prefixed with "__" to prevent collisions.
	__veyron2 "veyron.io/veyron/veyron2"
	__context "veyron.io/veyron/veyron2/context"
	__ipc "veyron.io/veyron/veyron2/ipc"
	__vdlutil "veyron.io/veyron/veyron2/vdl/vdlutil"
	__wiretype "veyron.io/veyron/veyron2/wiretype"
)

// TODO(toddw): Remove this line once the new signature support is done.
// It corrects a bug where __wiretype is unused in VDL pacakges where only
// bootstrap types are used on interfaces.
const _ = __wiretype.TypeIDInvalid

// PingPongClientMethods is the client interface
// containing PingPong methods.
//
// Simple service used in the agent tests.
type PingPongClientMethods interface {
	Ping(ctx __context.T, message string, opts ...__ipc.CallOpt) (string, error)
}

// PingPongClientStub adds universal methods to PingPongClientMethods.
type PingPongClientStub interface {
	PingPongClientMethods
	__ipc.UniversalServiceMethods
}

// PingPongClient returns a client stub for PingPong.
func PingPongClient(name string, opts ...__ipc.BindOpt) PingPongClientStub {
	var client __ipc.Client
	for _, opt := range opts {
		if clientOpt, ok := opt.(__ipc.Client); ok {
			client = clientOpt
		}
	}
	return implPingPongClientStub{name, client}
}

type implPingPongClientStub struct {
	name   string
	client __ipc.Client
}

func (c implPingPongClientStub) c(ctx __context.T) __ipc.Client {
	if c.client != nil {
		return c.client
	}
	return __veyron2.RuntimeFromContext(ctx).Client()
}

func (c implPingPongClientStub) Ping(ctx __context.T, i0 string, opts ...__ipc.CallOpt) (o0 string, err error) {
	var call __ipc.Call
	if call, err = c.c(ctx).StartCall(ctx, c.name, "Ping", []interface{}{i0}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&o0, &err); ierr != nil {
		err = ierr
	}
	return
}

func (c implPingPongClientStub) Signature(ctx __context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
	var call __ipc.Call
	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&o0, &err); ierr != nil {
		err = ierr
	}
	return
}

// PingPongServerMethods is the interface a server writer
// implements for PingPong.
//
// Simple service used in the agent tests.
type PingPongServerMethods interface {
	Ping(ctx __ipc.ServerContext, message string) (string, error)
}

// PingPongServerStubMethods is the server interface containing
// PingPong methods, as expected by ipc.Server.
// There is no difference between this interface and PingPongServerMethods
// since there are no streaming methods.
type PingPongServerStubMethods PingPongServerMethods

// PingPongServerStub adds universal methods to PingPongServerStubMethods.
type PingPongServerStub interface {
	PingPongServerStubMethods
	// Describe the PingPong interfaces.
	Describe__() []__ipc.InterfaceDesc
	// Signature will be replaced with Describe__.
	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}

// PingPongServer returns a server stub for PingPong.
// It converts an implementation of PingPongServerMethods into
// an object that may be used by ipc.Server.
func PingPongServer(impl PingPongServerMethods) PingPongServerStub {
	stub := implPingPongServerStub{
		impl: impl,
	}
	// Initialize GlobState; always check the stub itself first, to handle the
	// case where the user has the Glob method defined in their VDL source.
	if gs := __ipc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := __ipc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implPingPongServerStub struct {
	impl PingPongServerMethods
	gs   *__ipc.GlobState
}

func (s implPingPongServerStub) Ping(ctx __ipc.ServerContext, i0 string) (string, error) {
	return s.impl.Ping(ctx, i0)
}

func (s implPingPongServerStub) Globber() *__ipc.GlobState {
	return s.gs
}

func (s implPingPongServerStub) Describe__() []__ipc.InterfaceDesc {
	return []__ipc.InterfaceDesc{PingPongDesc}
}

// PingPongDesc describes the PingPong interface.
var PingPongDesc __ipc.InterfaceDesc = descPingPong

// descPingPong hides the desc to keep godoc clean.
var descPingPong = __ipc.InterfaceDesc{
	Name:    "PingPong",
	PkgPath: "veyron.io/veyron/veyron/security/agent/pingpong",
	Doc:     "// Simple service used in the agent tests.",
	Methods: []__ipc.MethodDesc{
		{
			Name: "Ping",
			InArgs: []__ipc.ArgDesc{
				{"message", ``}, // string
			},
			OutArgs: []__ipc.ArgDesc{
				{"", ``}, // string
				{"", ``}, // error
			},
		},
	},
}

func (s implPingPongServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
	// TODO(toddw): Replace with new Describe__ implementation.
	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
	result.Methods["Ping"] = __ipc.MethodSignature{
		InArgs: []__ipc.MethodArgument{
			{Name: "message", Type: 3},
		},
		OutArgs: []__ipc.MethodArgument{
			{Name: "", Type: 3},
			{Name: "", Type: 65},
		},
	}

	result.TypeDefs = []__vdlutil.Any{
		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}

	return result, nil
}
