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

package mounttable

import (
	// The non-user imports are prefixed with "_gen_" to prevent collisions.
	_gen_veyron2 "veyron2"
	_gen_ipc "veyron2/ipc"
	_gen_naming "veyron2/naming"
	_gen_rt "veyron2/rt"
	_gen_vdl "veyron2/vdl"
	_gen_wiretype "veyron2/wiretype"
)

// Collection is the interface the client binds and uses.
// Collection_InternalNoTagGetter is the interface without the TagGetter
// and UnresolveStep methods (both framework-added, rathern than user-defined),
// to enable embedding without method collisions.  Not to be used directly by
// clients.
type Collection_InternalNoTagGetter interface {

	// Export sets the value for a name.  Overwrite controls the behavior when
	// an entry exists, if Overwrite is true, then the binding is replaced,
	// otherwise the call fails with an error.  The Val must be no larger than
	// MaxSize bytes.
	Export(Val string, Overwrite bool, opts ..._gen_ipc.ClientCallOpt) (err error)
	// Lookup retrieves the value associated with a name.  Returns an error if
	// there is no such binding.
	Lookup(opts ..._gen_ipc.ClientCallOpt) (reply []byte, err error)
}
type Collection interface {
	_gen_vdl.TagGetter
	// UnresolveStep returns the names for the remote service, rooted at the
	// service's immediate namespace ancestor.
	UnresolveStep(opts ..._gen_ipc.ClientCallOpt) ([]string, error)
	Collection_InternalNoTagGetter
}

// CollectionService is the interface the server implements.
type CollectionService interface {

	// Export sets the value for a name.  Overwrite controls the behavior when
	// an entry exists, if Overwrite is true, then the binding is replaced,
	// otherwise the call fails with an error.  The Val must be no larger than
	// MaxSize bytes.
	Export(context _gen_ipc.Context, Val string, Overwrite bool) (err error)
	// Lookup retrieves the value associated with a name.  Returns an error if
	// there is no such binding.
	Lookup(context _gen_ipc.Context) (reply []byte, err error)
}

// BindCollection returns the client stub implementing the Collection
// interface.
//
// If no _gen_ipc.Client is specified, the default _gen_ipc.Client in the
// global Runtime is used.
func BindCollection(name string, opts ..._gen_ipc.BindOpt) (Collection, error) {
	var client _gen_ipc.Client
	switch len(opts) {
	case 0:
		client = _gen_rt.R().Client()
	case 1:
		switch o := opts[0].(type) {
		case _gen_veyron2.Runtime:
			client = o.Client()
		case _gen_ipc.Client:
			client = o
		default:
			return nil, _gen_vdl.ErrUnrecognizedOption
		}
	default:
		return nil, _gen_vdl.ErrTooManyOptionsToBind
	}
	stub := &clientStubCollection{client: client, name: name}

	return stub, nil
}

// NewServerCollection creates a new server stub.
//
// It takes a regular server implementing the CollectionService
// interface, and returns a new server stub.
func NewServerCollection(server CollectionService) interface{} {
	return &ServerStubCollection{
		service: server,
	}
}

// clientStubCollection implements Collection.
type clientStubCollection struct {
	client _gen_ipc.Client
	name   string
}

func (c *clientStubCollection) GetMethodTags(method string) []interface{} {
	return GetCollectionMethodTags(method)
}

func (__gen_c *clientStubCollection) Export(Val string, Overwrite bool, opts ..._gen_ipc.ClientCallOpt) (err error) {
	var call _gen_ipc.ClientCall
	if call, err = __gen_c.client.StartCall(__gen_c.name, "Export", []interface{}{Val, Overwrite}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubCollection) Lookup(opts ..._gen_ipc.ClientCallOpt) (reply []byte, err error) {
	var call _gen_ipc.ClientCall
	if call, err = __gen_c.client.StartCall(__gen_c.name, "Lookup", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

func (c *clientStubCollection) UnresolveStep(opts ..._gen_ipc.ClientCallOpt) (reply []string, err error) {
	var call _gen_ipc.ClientCall
	if call, err = c.client.StartCall(c.name, "UnresolveStep", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

// ServerStubCollection wraps a server that implements
// CollectionService and provides an object that satisfies
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubCollection struct {
	service CollectionService
}

func (s *ServerStubCollection) GetMethodTags(method string) []interface{} {
	return GetCollectionMethodTags(method)
}

func (s *ServerStubCollection) Signature(call _gen_ipc.ServerCall) (_gen_ipc.ServiceSignature, error) {
	result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
	result.Methods["Export"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{
			{Name: "Val", Type: 3},
			{Name: "Overwrite", Type: 2},
		},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 65},
		},
	}
	result.Methods["Lookup"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 67},
			{Name: "", Type: 65},
		},
	}

	result.TypeDefs = []_gen_vdl.Any{
		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, _gen_wiretype.SliceType{Elem: 0x42, Name: "", Tags: []string(nil)}}

	return result, nil
}

func (s *ServerStubCollection) UnresolveStep(call _gen_ipc.ServerCall) (reply []string, err error) {
	if unresolver, ok := s.service.(_gen_ipc.Unresolver); ok {
		return unresolver.UnresolveStep(call)
	}
	if call.Server() == nil {
		return
	}
	var published []string
	if published, err = call.Server().Published(); err != nil || published == nil {
		return
	}
	reply = make([]string, len(published))
	for i, p := range published {
		reply[i] = _gen_naming.Join(p, call.Name())
	}
	return
}

func (__gen_s *ServerStubCollection) Export(call _gen_ipc.ServerCall, Val string, Overwrite bool) (err error) {
	err = __gen_s.service.Export(call, Val, Overwrite)
	return
}

func (__gen_s *ServerStubCollection) Lookup(call _gen_ipc.ServerCall) (reply []byte, err error) {
	reply, err = __gen_s.service.Lookup(call)
	return
}

func GetCollectionMethodTags(method string) []interface{} {
	switch method {
	case "Export":
		return []interface{}{}
	case "Lookup":
		return []interface{}{}
	default:
		return nil
	}
}
