// 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"
)

// 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
	// JoinSyncGroup is invoked on a SyncGroup Admin and checks if
	// the requestor can join the SyncGroup.
	JoinSyncGroup(*context.T, ...rpc.CallOpt) 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) JoinSyncGroup(ctx *context.T, opts ...rpc.CallOpt) (err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "JoinSyncGroup", nil, nil, 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
	// JoinSyncGroup is invoked on a SyncGroup Admin and checks if
	// the requestor can join the SyncGroup.
	JoinSyncGroup(*context.T, rpc.ServerCall) 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) JoinSyncGroup(ctx *context.T, call rpc.ServerCall) error {
	return s.impl.JoinSyncGroup(ctx, call)
}

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.",
		},
		{
			Name: "PublishSyncGroup",
			Doc:  "// PublishSyncGroup is typically invoked on a \"central\" peer\n// to publish the SyncGroup.",
			InArgs: []rpc.ArgDesc{
				{"sg", ``}, // SyncGroup
			},
		},
		{
			Name: "JoinSyncGroup",
			Doc:  "// JoinSyncGroup is invoked on a SyncGroup Admin and checks if\n// the requestor can join the SyncGroup.",
		},
		{
			Name: "FetchBlob",
			Doc:  "// BlobSync methods.\n// FetchBlob returns the requested blob.",
		},
	},
}
