// 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 "v.io/core/veyron2"
	__context "v.io/core/veyron2/context"
	__ipc "v.io/core/veyron2/ipc"
	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
	__wiretype "v.io/core/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.GetClient(ctx)
}

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: "v.io/core/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
}
