// 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.

// Package xserver provides an alternate RPC server API with the goal of
// being simpler to use and understand.
package xrpc

import (
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/rpc"
	"v.io/v23/security"
)

type Server struct {
	s rpc.Server
}

// NewServer creates a new Server instance to serve a service object.
//
// The server will listen for network connections as specified by the
// ListenSpec attached to ctx. Depending on your RuntimeFactory, 'roaming'
// support may be enabled. In this mode the server will listen for
// changes in the network configuration using a Stream created on the
// supplied Publisher and change the set of Endpoints it publishes to
// the mount table accordingly.
//
// The server associates object with name by publishing the address of
// this server in the namespace under the supplied name and using
// authorizer to authorize access to it. RPCs invoked on the supplied
// name will be delivered to methods implemented by the supplied
// object.  Reflection is used to match requests to the object's
// method set.  As a special-case, if the object implements the
// Invoker interface, the Invoker is used to invoke methods directly,
// without reflection.  If name is an empty string, no attempt will
// made to publish.
func NewServer(ctx *context.T, name string, object interface{}, auth security.Authorizer, opts ...rpc.ServerOpt) (*Server, error) {
	s, err := v23.NewServer(ctx, opts...)
	if err != nil {
		return nil, err
	}
	if _, err = s.Listen(v23.GetListenSpec(ctx)); err != nil {
		s.Stop()
		return nil, err
	}
	if err = s.Serve(name, object, auth); err != nil {
		s.Stop()
		return nil, err
	}
	return &Server{s: s}, nil
}

// NewDispatchingServer creates a new Server instance to serve a given dispatcher.
//
// The server will listen for network connections as specified by the
// ListenSpec attached to ctx. Depending on your RuntimeFactory, 'roaming'
// support may be enabled. In this mode the server will listen for
// changes in the network configuration using a Stream created on the
// supplied Publisher and change the set of Endpoints it publishes to
// the mount table accordingly.
//
// The server associates dispatcher with the portion of the namespace
// for which name is a prefix by publishing the address of this server
// to the namespace under the supplied name. If name is an empty
// string, no attempt will made to publish. RPCs invoked on the
// supplied name will be delivered to the supplied Dispatcher's Lookup
// method which will in turn return the object and security.Authorizer
// used to serve the actual RPC call.  If name is an empty string, no
// attempt will made to publish that name to a mount table.
func NewDispatchingServer(ctx *context.T, name string, disp rpc.Dispatcher, opts ...rpc.ServerOpt) (*Server, error) {
	s, err := v23.NewServer(ctx, opts...)
	if err != nil {
		return nil, err
	}
	if _, err = s.Listen(v23.GetListenSpec(ctx)); err != nil {
		return nil, err
	}
	if err = s.ServeDispatcher(name, disp); err != nil {
		return nil, err
	}
	return &Server{s: s}, nil
}

// AddName adds the specified name to the mount table for this server.
// AddName may be called multiple times.
func (s *Server) AddName(name string, properties naming.Properties) error {
	return s.s.AddName(name, properties)
}

// RemoveName removes the specified name from the mount table.
// RemoveName may be called multiple times.
func (s *Server) RemoveName(name string) {
	s.s.RemoveName(name)
}

// Status returns the current status of the server, see ServerStatus
// for details.
func (s *Server) Status() rpc.ServerStatus {
	return s.s.Status()
}

// WatchNetwork registers a channel over which NetworkChange's will
// be sent. The Server will not block sending data over this channel
// and hence change events may be lost if the caller doesn't ensure
// there is sufficient buffering in the channel.
func (s *Server) WatchNetwork(ch chan<- rpc.NetworkChange) {
	s.s.WatchNetwork(ch)
}

// UnwatchNetwork unregisters a channel previously registered using
// WatchNetwork.
func (s *Server) UnwatchNetwork(ch chan<- rpc.NetworkChange) {
	s.s.UnwatchNetwork(ch)
}

// Stop gracefully stops all services on this Server.  New calls are
// rejected, but any in-flight calls are allowed to complete.  All
// published mountpoints are unmounted.  This call waits for this
// process to complete, and returns once the server has been shut down.
func (s *Server) Stop() error {
	return s.s.Stop()
}
