// 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 (
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
)

func __VDLEnsureNativeBuilt_chat() {
}

// ChatClientMethods is the client interface
// containing Chat methods.
type ChatClientMethods interface {
	// SendMessage sends a message to a user.
	SendMessage(_ *context.T, text string, _ ...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(_ *context.T, _ 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
			},
		},
	},
}
