// 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: sync.vdl

package interfaces

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

	// VDL user imports
	"v.io/syncbase/v23/services/syncbase/nosql"
	"v.io/v23/security/access"
)

// SyncClientMethods is the client interface
// containing Sync methods.
//
// Sync defines methods for data exchange between Syncbases.
// TODO(hpucha): Flesh this out further.
type SyncClientMethods interface {
	// GetDeltas returns the responder's current generation vector
	// and all the missing log records when compared to the
	// initiator's generation vector.
	GetDeltas(*context.T, ...rpc.CallOpt) error
	// PublishSyncGroup is typically invoked on a "central" peer
	// to publish the SyncGroup.
	PublishSyncGroup(ctx *context.T, sg SyncGroup, opts ...rpc.CallOpt) error
	// JoinSyncGroupAtAdmin is invoked by a prospective SyncGroup member's
	// Syncbase on a SyncGroup admin. It checks whether the requestor is
	// allowed to join the named SyncGroup, and if so, adds the requestor to
	// the SyncGroup.
	JoinSyncGroupAtAdmin(ctx *context.T, sgName string, joinerName string, myInfo nosql.SyncGroupMemberInfo, opts ...rpc.CallOpt) (SyncGroup, error)
	// BlobSync methods.
	// FetchBlob returns the requested blob.
	FetchBlob(*context.T, ...rpc.CallOpt) error
}

// SyncClientStub adds universal methods to SyncClientMethods.
type SyncClientStub interface {
	SyncClientMethods
	rpc.UniversalServiceMethods
}

// SyncClient returns a client stub for Sync.
func SyncClient(name string) SyncClientStub {
	return implSyncClientStub{name}
}

type implSyncClientStub struct {
	name string
}

func (c implSyncClientStub) GetDeltas(ctx *context.T, opts ...rpc.CallOpt) (err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "GetDeltas", nil, nil, opts...)
	return
}

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

func (c implSyncClientStub) JoinSyncGroupAtAdmin(ctx *context.T, i0 string, i1 string, i2 nosql.SyncGroupMemberInfo, opts ...rpc.CallOpt) (o0 SyncGroup, err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "JoinSyncGroupAtAdmin", []interface{}{i0, i1, i2}, []interface{}{&o0}, opts...)
	return
}

func (c implSyncClientStub) FetchBlob(ctx *context.T, opts ...rpc.CallOpt) (err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "FetchBlob", nil, nil, opts...)
	return
}

// SyncServerMethods is the interface a server writer
// implements for Sync.
//
// Sync defines methods for data exchange between Syncbases.
// TODO(hpucha): Flesh this out further.
type SyncServerMethods interface {
	// GetDeltas returns the responder's current generation vector
	// and all the missing log records when compared to the
	// initiator's generation vector.
	GetDeltas(*context.T, rpc.ServerCall) error
	// PublishSyncGroup is typically invoked on a "central" peer
	// to publish the SyncGroup.
	PublishSyncGroup(ctx *context.T, call rpc.ServerCall, sg SyncGroup) error
	// JoinSyncGroupAtAdmin is invoked by a prospective SyncGroup member's
	// Syncbase on a SyncGroup admin. It checks whether the requestor is
	// allowed to join the named SyncGroup, and if so, adds the requestor to
	// the SyncGroup.
	JoinSyncGroupAtAdmin(ctx *context.T, call rpc.ServerCall, sgName string, joinerName string, myInfo nosql.SyncGroupMemberInfo) (SyncGroup, error)
	// BlobSync methods.
	// FetchBlob returns the requested blob.
	FetchBlob(*context.T, rpc.ServerCall) error
}

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

// SyncServerStub adds universal methods to SyncServerStubMethods.
type SyncServerStub interface {
	SyncServerStubMethods
	// Describe the Sync interfaces.
	Describe__() []rpc.InterfaceDesc
}

// SyncServer returns a server stub for Sync.
// It converts an implementation of SyncServerMethods into
// an object that may be used by rpc.Server.
func SyncServer(impl SyncServerMethods) SyncServerStub {
	stub := implSyncServerStub{
		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 implSyncServerStub struct {
	impl SyncServerMethods
	gs   *rpc.GlobState
}

func (s implSyncServerStub) GetDeltas(ctx *context.T, call rpc.ServerCall) error {
	return s.impl.GetDeltas(ctx, call)
}

func (s implSyncServerStub) PublishSyncGroup(ctx *context.T, call rpc.ServerCall, i0 SyncGroup) error {
	return s.impl.PublishSyncGroup(ctx, call, i0)
}

func (s implSyncServerStub) JoinSyncGroupAtAdmin(ctx *context.T, call rpc.ServerCall, i0 string, i1 string, i2 nosql.SyncGroupMemberInfo) (SyncGroup, error) {
	return s.impl.JoinSyncGroupAtAdmin(ctx, call, i0, i1, i2)
}

func (s implSyncServerStub) FetchBlob(ctx *context.T, call rpc.ServerCall) error {
	return s.impl.FetchBlob(ctx, call)
}

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

func (s implSyncServerStub) Describe__() []rpc.InterfaceDesc {
	return []rpc.InterfaceDesc{SyncDesc}
}

// SyncDesc describes the Sync interface.
var SyncDesc rpc.InterfaceDesc = descSync

// descSync hides the desc to keep godoc clean.
var descSync = rpc.InterfaceDesc{
	Name:    "Sync",
	PkgPath: "v.io/syncbase/x/ref/services/syncbase/server/interfaces",
	Doc:     "// Sync defines methods for data exchange between Syncbases.\n// TODO(hpucha): Flesh this out further.",
	Methods: []rpc.MethodDesc{
		{
			Name: "GetDeltas",
			Doc:  "// GetDeltas returns the responder's current generation vector\n// and all the missing log records when compared to the\n// initiator's generation vector.",
			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Read"))},
		},
		{
			Name: "PublishSyncGroup",
			Doc:  "// PublishSyncGroup is typically invoked on a \"central\" peer\n// to publish the SyncGroup.",
			InArgs: []rpc.ArgDesc{
				{"sg", ``}, // SyncGroup
			},
			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Write"))},
		},
		{
			Name: "JoinSyncGroupAtAdmin",
			Doc:  "// JoinSyncGroupAtAdmin is invoked by a prospective SyncGroup member's\n// Syncbase on a SyncGroup admin. It checks whether the requestor is\n// allowed to join the named SyncGroup, and if so, adds the requestor to\n// the SyncGroup.",
			InArgs: []rpc.ArgDesc{
				{"sgName", ``},     // string
				{"joinerName", ``}, // string
				{"myInfo", ``},     // nosql.SyncGroupMemberInfo
			},
			OutArgs: []rpc.ArgDesc{
				{"", ``}, // SyncGroup
			},
			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Read"))},
		},
		{
			Name: "FetchBlob",
			Doc:  "// BlobSync methods.\n// FetchBlob returns the requested blob.",
			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Read"))},
		},
	},
}
