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

package node

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

// ConfigClientMethods is the client interface
// containing Config methods.
//
// Config is an RPC API to the config service.
type ConfigClientMethods interface {
	// Set sets the value for key.
	Set(ctx __context.T, key string, value string, opts ...__ipc.CallOpt) error
}

// ConfigClientStub adds universal methods to ConfigClientMethods.
type ConfigClientStub interface {
	ConfigClientMethods
	__ipc.UniversalServiceMethods
}

// ConfigClient returns a client stub for Config.
func ConfigClient(name string, opts ...__ipc.BindOpt) ConfigClientStub {
	var client __ipc.Client
	for _, opt := range opts {
		if clientOpt, ok := opt.(__ipc.Client); ok {
			client = clientOpt
		}
	}
	return implConfigClientStub{name, client}
}

type implConfigClientStub struct {
	name   string
	client __ipc.Client
}

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

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

func (c implConfigClientStub) 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
}

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

// ConfigServerMethods is the interface a server writer
// implements for Config.
//
// Config is an RPC API to the config service.
type ConfigServerMethods interface {
	// Set sets the value for key.
	Set(ctx __ipc.ServerContext, key string, value string) error
}

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

// ConfigServerStub adds universal methods to ConfigServerStubMethods.
type ConfigServerStub interface {
	ConfigServerStubMethods
	// GetMethodTags will be replaced with DescribeInterfaces.
	GetMethodTags(ctx __ipc.ServerContext, method string) ([]interface{}, error)
	// Signature will be replaced with DescribeInterfaces.
	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}

// ConfigServer returns a server stub for Config.
// It converts an implementation of ConfigServerMethods into
// an object that may be used by ipc.Server.
func ConfigServer(impl ConfigServerMethods) ConfigServerStub {
	stub := implConfigServerStub{
		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 implConfigServerStub struct {
	impl ConfigServerMethods
	gs   *__ipc.GlobState
}

func (s implConfigServerStub) Set(ctx __ipc.ServerContext, i0 string, i1 string) error {
	return s.impl.Set(ctx, i0, i1)
}

func (s implConfigServerStub) VGlob() *__ipc.GlobState {
	return s.gs
}

func (s implConfigServerStub) GetMethodTags(ctx __ipc.ServerContext, method string) ([]interface{}, error) {
	// TODO(toddw): Replace with new DescribeInterfaces implementation.
	switch method {
	case "Set":
		return []interface{}{}, nil
	default:
		return nil, nil
	}
}

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

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

	return result, nil
}
