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

import (
	"time"

	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/options"
	"v.io/v23/rpc"

	"v.io/x/ref/lib/apilog"
)

// PreferredProtocols instructs the Runtime implementation to select
// endpoints with the specified protocols when a Client makes a call
// and to order them in the specified order.
type PreferredProtocols []string

func (PreferredProtocols) RPCClientOpt() {
	defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}

// This option is used to sort and filter the endpoints when resolving the
// proxy name from a mounttable.
type PreferredServerResolveProtocols []string

func (PreferredServerResolveProtocols) RPCServerOpt() {
	defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}

// ReservedNameDispatcher specifies the dispatcher that controls access
// to framework managed portion of the namespace.
type ReservedNameDispatcher struct {
	Dispatcher rpc.Dispatcher
}

func (ReservedNameDispatcher) RPCServerOpt() {
	defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}

// IdleConnectionExpiry is the amount of the time after which the connection cache
// will close idle connections.
type IdleConnectionExpiry time.Duration

func (IdleConnectionExpiry) RPCClientOpt() {
	defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}
func (IdleConnectionExpiry) RPCServerOpt() {
	defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}

type connectionOpts struct {
	connDeadline   time.Time
	channelTimeout time.Duration
	useOnlyCached  bool
	noRetry        bool
}

func getConnectionOptions(ctx *context.T, opts []rpc.CallOpt) *connectionOpts {
	now := time.Now()
	var copts connectionOpts
	for _, o := range opts {
		switch t := o.(type) {
		case options.ConnectionTimeout:
			if dur := time.Duration(t); dur == 0 {
				copts.useOnlyCached = true
			} else {
				// Use the minimum of all the timeouts passed in.
				if dl := now.Add(dur); dl.Before(copts.connDeadline) || copts.connDeadline.IsZero() {
					copts.connDeadline = dl
				}
			}
		case options.ChannelTimeout:
			// Use the minimum channel timeout.
			if dur := time.Duration(t); dur < copts.channelTimeout || copts.channelTimeout == 0 {
				copts.channelTimeout = time.Duration(t)
			}
		case options.NoRetry:
			copts.noRetry = true
		}
	}
	// If the context deadline is sooner than connection deadline, use it instead.
	if dl, hasDl := ctx.Deadline(); hasDl && (dl.Before(copts.connDeadline) || copts.connDeadline.IsZero()) {
		copts.connDeadline = dl
	}
	// If no deadline has been set yet, use the default call timeout.
	if copts.connDeadline.IsZero() {
		copts.connDeadline = now.Add(defaultCallTimeout)
	}
	return &copts
}

func getNoNamespaceOpt(opts []rpc.CallOpt) bool {
	for _, o := range opts {
		switch o.(type) {
		case options.Preresolved:
			return true
		}
	}
	return false
}

func getNamespaceOpts(opts []rpc.CallOpt) (resolveOpts []naming.NamespaceOpt) {
	for _, o := range opts {
		if r, ok := o.(naming.NamespaceOpt); ok {
			resolveOpts = append(resolveOpts, r)
		}
	}
	return
}
