// 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"
)

// 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
}

// 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
}

// 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
			},
		},
	},
}
