// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file was auto-generated by the vanadium vdl tool.
// Source: chat.vdl

package vdl

import (
	// VDL system imports
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
)

// ChatClientMethods is the client interface
// containing Chat methods.
type ChatClientMethods interface {
	// SendMessage sends a message to a user.
	SendMessage(ctx *context.T, text string, opts ...rpc.CallOpt) error
}

// ChatClientStub adds universal methods to ChatClientMethods.
type ChatClientStub interface {
	ChatClientMethods
	rpc.UniversalServiceMethods
}

// ChatClient returns a client stub for Chat.
func ChatClient(name string) ChatClientStub {
	return implChatClientStub{name}
}

type implChatClientStub struct {
	name string
}

func (c implChatClientStub) SendMessage(ctx *context.T, i0 string, opts ...rpc.CallOpt) (err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "SendMessage", []interface{}{i0}, nil, opts...)
	return
}

// ChatServerMethods is the interface a server writer
// implements for Chat.
type ChatServerMethods interface {
	// SendMessage sends a message to a user.
	SendMessage(ctx *context.T, call rpc.ServerCall, text string) error
}

// ChatServerStubMethods is the server interface containing
// Chat methods, as expected by rpc.Server.
// There is no difference between this interface and ChatServerMethods
// since there are no streaming methods.
type ChatServerStubMethods ChatServerMethods

// ChatServerStub adds universal methods to ChatServerStubMethods.
type ChatServerStub interface {
	ChatServerStubMethods
	// Describe the Chat interfaces.
	Describe__() []rpc.InterfaceDesc
}

// ChatServer returns a server stub for Chat.
// It converts an implementation of ChatServerMethods into
// an object that may be used by rpc.Server.
func ChatServer(impl ChatServerMethods) ChatServerStub {
	stub := implChatServerStub{
		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 := rpc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := rpc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implChatServerStub struct {
	impl ChatServerMethods
	gs   *rpc.GlobState
}

func (s implChatServerStub) SendMessage(ctx *context.T, call rpc.ServerCall, i0 string) error {
	return s.impl.SendMessage(ctx, call, i0)
}

func (s implChatServerStub) Globber() *rpc.GlobState {
	return s.gs
}

func (s implChatServerStub) Describe__() []rpc.InterfaceDesc {
	return []rpc.InterfaceDesc{ChatDesc}
}

// ChatDesc describes the Chat interface.
var ChatDesc rpc.InterfaceDesc = descChat

// descChat hides the desc to keep godoc clean.
var descChat = rpc.InterfaceDesc{
	Name:    "Chat",
	PkgPath: "v.io/x/chat/vdl",
	Methods: []rpc.MethodDesc{
		{
			Name: "SendMessage",
			Doc:  "// SendMessage sends a message to a user.",
			InArgs: []rpc.ArgDesc{
				{"text", ``}, // string
			},
		},
	},
}
