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

package inspector

import (
	// The non-user imports are prefixed with "_gen_" to prevent collisions.
	_gen_io "io"
	_gen_context "veyron2/context"
	_gen_ipc "veyron2/ipc"
	_gen_naming "veyron2/naming"
	_gen_rt "veyron2/rt"
	_gen_vdlutil "veyron2/vdl/vdlutil"
	_gen_wiretype "veyron2/wiretype"
)

type Details struct {
	Name string
	Size int64
	Mode uint32
	// TODO: add native time format to the idl+vom
	// Seconds since the start of the Unix epoch
	ModUnixSecs int64
	// Nanoseconds in the current second
	ModNano int32
	IsDir   bool
}

// TODO(bprosnitz) Remove this line once signatures are updated to use typevals.
// It corrects a bug where _gen_wiretype is unused in VDL pacakges where only bootstrap types are used on interfaces.
const _ = _gen_wiretype.TypeIDInvalid

// Inspector is the interface the client binds and uses.
// Inspector_ExcludingUniversal is the interface without internal framework-added methods
// to enable embedding without method collisions.  Not to be used directly by clients.
type Inspector_ExcludingUniversal interface {
	Ls(ctx _gen_context.T, Glob string, opts ..._gen_ipc.CallOpt) (reply InspectorLsCall, err error)
	LsDetails(ctx _gen_context.T, Glob string, opts ..._gen_ipc.CallOpt) (reply InspectorLsDetailsCall, err error)
}
type Inspector interface {
	_gen_ipc.UniversalServiceMethods
	Inspector_ExcludingUniversal
}

// InspectorService is the interface the server implements.
type InspectorService interface {
	Ls(context _gen_ipc.ServerContext, Glob string, stream InspectorServiceLsStream) (err error)
	LsDetails(context _gen_ipc.ServerContext, Glob string, stream InspectorServiceLsDetailsStream) (err error)
}

// InspectorLsCall is the interface for call object of the method
// Ls in the service interface Inspector.
type InspectorLsCall interface {
	// RecvStream returns the recv portion of the stream
	RecvStream() interface {
		// Advance stages an element so the client can retrieve it
		// with Value.  Advance returns true iff there is an
		// element to retrieve.  The client must call Advance before
		// calling Value. Advance may block if an element is not
		// immediately available.
		Advance() bool

		// Value returns the element that was staged by Advance.
		// Value may panic if Advance returned false or was not
		// called at all.  Value does not block.
		Value() string

		// Err returns a non-nil error iff the stream encountered
		// any errors.  Err does not block.
		Err() error
	}

	// Finish blocks until the server is done and returns the positional
	// return values for call.
	//
	// If Cancel has been called, Finish will return immediately; the output of
	// Finish could either be an error signalling cancelation, or the correct
	// positional return values from the server depending on the timing of the
	// call.
	//
	// Calling Finish is mandatory for releasing stream resources, unless Cancel
	// has been called or any of the other methods return an error.
	// Finish should be called at most once.
	Finish() (err error)

	// Cancel cancels the RPC, notifying the server to stop processing.  It
	// is safe to call Cancel concurrently with any of the other stream methods.
	// Calling Cancel after Finish has returned is a no-op.
	Cancel()
}

type implInspectorLsStreamIterator struct {
	clientCall _gen_ipc.Call
	val        string
	err        error
}

func (c *implInspectorLsStreamIterator) Advance() bool {
	c.err = c.clientCall.Recv(&c.val)
	return c.err == nil
}

func (c *implInspectorLsStreamIterator) Value() string {
	return c.val
}

func (c *implInspectorLsStreamIterator) Err() error {
	if c.err == _gen_io.EOF {
		return nil
	}
	return c.err
}

// Implementation of the InspectorLsCall interface that is not exported.
type implInspectorLsCall struct {
	clientCall _gen_ipc.Call
	readStream implInspectorLsStreamIterator
}

func (c *implInspectorLsCall) RecvStream() interface {
	Advance() bool
	Value() string
	Err() error
} {
	return &c.readStream
}

func (c *implInspectorLsCall) Finish() (err error) {
	if ierr := c.clientCall.Finish(&err); ierr != nil {
		err = ierr
	}
	return
}

func (c *implInspectorLsCall) Cancel() {
	c.clientCall.Cancel()
}

type implInspectorServiceLsStreamSender struct {
	serverCall _gen_ipc.ServerCall
}

func (s *implInspectorServiceLsStreamSender) Send(item string) error {
	return s.serverCall.Send(item)
}

// InspectorServiceLsStream is the interface for streaming responses of the method
// Ls in the service interface Inspector.
type InspectorServiceLsStream interface {
	// SendStream returns the send portion of the stream.
	SendStream() interface {
		// Send places the item onto the output stream, blocking if there is no buffer
		// space available.  If the client has canceled, an error is returned.
		Send(item string) error
	}
}

// Implementation of the InspectorServiceLsStream interface that is not exported.
type implInspectorServiceLsStream struct {
	writer implInspectorServiceLsStreamSender
}

func (s *implInspectorServiceLsStream) SendStream() interface {
	// Send places the item onto the output stream, blocking if there is no buffer
	// space available.  If the client has canceled, an error is returned.
	Send(item string) error
} {
	return &s.writer
}

// InspectorLsDetailsCall is the interface for call object of the method
// LsDetails in the service interface Inspector.
type InspectorLsDetailsCall interface {
	// RecvStream returns the recv portion of the stream
	RecvStream() interface {
		// Advance stages an element so the client can retrieve it
		// with Value.  Advance returns true iff there is an
		// element to retrieve.  The client must call Advance before
		// calling Value. Advance may block if an element is not
		// immediately available.
		Advance() bool

		// Value returns the element that was staged by Advance.
		// Value may panic if Advance returned false or was not
		// called at all.  Value does not block.
		Value() Details

		// Err returns a non-nil error iff the stream encountered
		// any errors.  Err does not block.
		Err() error
	}

	// Finish blocks until the server is done and returns the positional
	// return values for call.
	//
	// If Cancel has been called, Finish will return immediately; the output of
	// Finish could either be an error signalling cancelation, or the correct
	// positional return values from the server depending on the timing of the
	// call.
	//
	// Calling Finish is mandatory for releasing stream resources, unless Cancel
	// has been called or any of the other methods return an error.
	// Finish should be called at most once.
	Finish() (err error)

	// Cancel cancels the RPC, notifying the server to stop processing.  It
	// is safe to call Cancel concurrently with any of the other stream methods.
	// Calling Cancel after Finish has returned is a no-op.
	Cancel()
}

type implInspectorLsDetailsStreamIterator struct {
	clientCall _gen_ipc.Call
	val        Details
	err        error
}

func (c *implInspectorLsDetailsStreamIterator) Advance() bool {
	c.val = Details{}
	c.err = c.clientCall.Recv(&c.val)
	return c.err == nil
}

func (c *implInspectorLsDetailsStreamIterator) Value() Details {
	return c.val
}

func (c *implInspectorLsDetailsStreamIterator) Err() error {
	if c.err == _gen_io.EOF {
		return nil
	}
	return c.err
}

// Implementation of the InspectorLsDetailsCall interface that is not exported.
type implInspectorLsDetailsCall struct {
	clientCall _gen_ipc.Call
	readStream implInspectorLsDetailsStreamIterator
}

func (c *implInspectorLsDetailsCall) RecvStream() interface {
	Advance() bool
	Value() Details
	Err() error
} {
	return &c.readStream
}

func (c *implInspectorLsDetailsCall) Finish() (err error) {
	if ierr := c.clientCall.Finish(&err); ierr != nil {
		err = ierr
	}
	return
}

func (c *implInspectorLsDetailsCall) Cancel() {
	c.clientCall.Cancel()
}

type implInspectorServiceLsDetailsStreamSender struct {
	serverCall _gen_ipc.ServerCall
}

func (s *implInspectorServiceLsDetailsStreamSender) Send(item Details) error {
	return s.serverCall.Send(item)
}

// InspectorServiceLsDetailsStream is the interface for streaming responses of the method
// LsDetails in the service interface Inspector.
type InspectorServiceLsDetailsStream interface {
	// SendStream returns the send portion of the stream.
	SendStream() interface {
		// Send places the item onto the output stream, blocking if there is no buffer
		// space available.  If the client has canceled, an error is returned.
		Send(item Details) error
	}
}

// Implementation of the InspectorServiceLsDetailsStream interface that is not exported.
type implInspectorServiceLsDetailsStream struct {
	writer implInspectorServiceLsDetailsStreamSender
}

func (s *implInspectorServiceLsDetailsStream) SendStream() interface {
	// Send places the item onto the output stream, blocking if there is no buffer
	// space available.  If the client has canceled, an error is returned.
	Send(item Details) error
} {
	return &s.writer
}

// BindInspector returns the client stub implementing the Inspector
// interface.
//
// If no _gen_ipc.Client is specified, the default _gen_ipc.Client in the
// global Runtime is used.
func BindInspector(name string, opts ..._gen_ipc.BindOpt) (Inspector, 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_ipc.Client:
			client = o
		default:
			return nil, _gen_vdlutil.ErrUnrecognizedOption
		}
	default:
		return nil, _gen_vdlutil.ErrTooManyOptionsToBind
	}
	stub := &clientStubInspector{client: client, name: name}

	return stub, nil
}

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

// clientStubInspector implements Inspector.
type clientStubInspector struct {
	client _gen_ipc.Client
	name   string
}

func (__gen_c *clientStubInspector) Ls(ctx _gen_context.T, Glob string, opts ..._gen_ipc.CallOpt) (reply InspectorLsCall, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Ls", []interface{}{Glob}, opts...); err != nil {
		return
	}
	reply = &implInspectorLsCall{clientCall: call, readStream: implInspectorLsStreamIterator{clientCall: call}}
	return
}

func (__gen_c *clientStubInspector) LsDetails(ctx _gen_context.T, Glob string, opts ..._gen_ipc.CallOpt) (reply InspectorLsDetailsCall, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "LsDetails", []interface{}{Glob}, opts...); err != nil {
		return
	}
	reply = &implInspectorLsDetailsCall{clientCall: call, readStream: implInspectorLsDetailsStreamIterator{clientCall: call}}
	return
}

func (__gen_c *clientStubInspector) UnresolveStep(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply []string, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "UnresolveStep", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubInspector) Signature(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply _gen_ipc.ServiceSignature, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Signature", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubInspector) GetMethodTags(ctx _gen_context.T, method string, opts ..._gen_ipc.CallOpt) (reply []interface{}, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "GetMethodTags", []interface{}{method}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

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

func (__gen_s *ServerStubInspector) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
	// TODO(bprosnitz) GetMethodTags() will be replaces with Signature().
	// Note: This exhibits some weird behavior like returning a nil error if the method isn't found.
	// This will change when it is replaced with Signature().
	switch method {
	case "Ls":
		return []interface{}{}, nil
	case "LsDetails":
		return []interface{}{}, nil
	default:
		return nil, nil
	}
}

func (__gen_s *ServerStubInspector) Signature(call _gen_ipc.ServerCall) (_gen_ipc.ServiceSignature, error) {
	result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
	result.Methods["Ls"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{
			{Name: "Glob", Type: 3},
		},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 65},
		},

		OutStream: 3,
	}
	result.Methods["LsDetails"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{
			{Name: "Glob", Type: 3},
		},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 65},
		},

		OutStream: 66,
	}

	result.TypeDefs = []_gen_vdlutil.Any{
		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, _gen_wiretype.StructType{
			[]_gen_wiretype.FieldType{
				_gen_wiretype.FieldType{Type: 0x3, Name: "Name"},
				_gen_wiretype.FieldType{Type: 0x25, Name: "Size"},
				_gen_wiretype.FieldType{Type: 0x34, Name: "Mode"},
				_gen_wiretype.FieldType{Type: 0x25, Name: "ModUnixSecs"},
				_gen_wiretype.FieldType{Type: 0x24, Name: "ModNano"},
				_gen_wiretype.FieldType{Type: 0x2, Name: "IsDir"},
			},
			"veyron/examples/inspector.Details", []string(nil)},
	}

	return result, nil
}

func (__gen_s *ServerStubInspector) UnresolveStep(call _gen_ipc.ServerCall) (reply []string, err error) {
	if unresolver, ok := __gen_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 *ServerStubInspector) Ls(call _gen_ipc.ServerCall, Glob string) (err error) {
	stream := &implInspectorServiceLsStream{writer: implInspectorServiceLsStreamSender{serverCall: call}}
	err = __gen_s.service.Ls(call, Glob, stream)
	return
}

func (__gen_s *ServerStubInspector) LsDetails(call _gen_ipc.ServerCall, Glob string) (err error) {
	stream := &implInspectorServiceLsDetailsStream{writer: implInspectorServiceLsDetailsStreamSender{serverCall: call}}
	err = __gen_s.service.LsDetails(call, Glob, stream)
	return
}
