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

import (
	"strings"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/glob"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/verror"

	"v.io/x/ref/services/role"
)

var (
	errNoLocalBlessings = verror.Register("v.io/x/ref/services/role/roled/internal/noLocalBlessings", verror.NoRetry, "{1:}{2:} no local blessings")
)

type roleService struct {
	serverConfig *serverConfig
	role         string
	roleConfig   *Config
}

func (i *roleService) SeekBlessings(ctx *context.T, call rpc.ServerCall) (security.Blessings, error) {
	remoteBlessingNames, _ := security.RemoteBlessingNames(ctx, call.Security())
	ctx.Infof("%q.SeekBlessings() called by %q", i.role, remoteBlessingNames)

	members := i.filterNonMembers(remoteBlessingNames)
	if len(members) == 0 {
		// The Authorizer should already have caught that.
		return security.Blessings{}, verror.New(verror.ErrNoAccess, ctx)
	}

	extensions := extensions(i.roleConfig, i.role, members)
	caveats, err := caveats(ctx, i.roleConfig)
	if err != nil {
		return security.Blessings{}, err
	}

	return createBlessings(ctx, call.Security(), i.roleConfig, v23.GetPrincipal(ctx), extensions, caveats, i.serverConfig.dischargerLocation)
}

func (i *roleService) GlobChildren__(ctx *context.T, call rpc.GlobChildrenServerCall, m *glob.Element) error {
	return globChildren(ctx, call, i.serverConfig, m)
}

// filterNonMembers returns only the blessing names that are authorized members
// for the role.
func (i *roleService) filterNonMembers(blessingNames []string) []string {
	var results []string
	for _, name := range blessingNames {
		// It is not enough to know if the pattern is matched by the
		// blessings. We need to know exactly which names matched.
		// These names will be used later to construct the role
		// blessings.
		for _, pattern := range i.roleConfig.Members {
			if pattern.MatchedBy(name) {
				results = append(results, name)
				break
			}
		}
	}
	return results
}

func extensions(config *Config, roleStr string, blessingNames []string) []string {
	// roleStr is the suffix of a veyron object name, but extensions are for
	// blessings, so do the conversion.
	roleStr = strings.Replace(roleStr, "/", security.ChainSeparator, -1)
	if !config.Extend {
		return []string{roleStr}
	}
	var extensions []string
	for _, b := range blessingNames {
		b = strings.TrimSuffix(b, security.ChainSeparator+role.RoleSuffix)
		extensions = append(extensions, roleStr+security.ChainSeparator+b)
	}
	return extensions
}

func caveats(ctx *context.T, config *Config) ([]security.Caveat, error) {
	var caveats []security.Caveat
	if config.Expiry != "" {
		d, err := time.ParseDuration(config.Expiry)
		if err != nil {
			return nil, verror.Convert(verror.ErrInternal, ctx, err)
		}
		expiry, err := security.NewExpiryCaveat(time.Now().Add(d))
		if err != nil {
			return nil, verror.Convert(verror.ErrInternal, ctx, err)
		}
		caveats = append(caveats, expiry)
	}
	if len(config.Peers) != 0 {
		peer, err := security.NewCaveat(security.PeerBlessingsCaveat, config.Peers)
		if err != nil {
			return nil, verror.Convert(verror.ErrInternal, ctx, err)
		}
		caveats = append(caveats, peer)
	}
	return caveats, nil
}

func createBlessings(ctx *context.T, call security.Call, config *Config, principal security.Principal, extensions []string, caveats []security.Caveat, dischargerLocation string) (security.Blessings, error) {
	blessWith := call.LocalBlessings()
	blessWithNames := security.LocalBlessingNames(ctx, call)
	publicKey := call.RemoteBlessings().PublicKey()
	if len(blessWithNames) == 0 {
		return security.Blessings{}, verror.New(errNoLocalBlessings, ctx)
	}

	var ret security.Blessings
	for _, ext := range extensions {
		cav := caveats
		if config.Audit {
			// TODO(rthellend): This third-party caveat will only work with a single
			// discharger service. We need a way to allow multiple instances of this
			// service to be interchangeable.

			fullNames := make([]string, len(blessWithNames))
			for i, n := range blessWithNames {
				fullNames[i] = n + security.ChainSeparator + ext
			}
			loggingCaveat, err := security.NewCaveat(LoggingCaveat, fullNames)
			if err != nil {
				return security.Blessings{}, verror.Convert(verror.ErrInternal, ctx, err)
			}
			thirdParty, err := security.NewPublicKeyCaveat(principal.PublicKey(), dischargerLocation, security.ThirdPartyRequirements{
				ReportServer:    true,
				ReportMethod:    true,
				ReportArguments: true,
			}, loggingCaveat)
			if err != nil {
				return security.Blessings{}, verror.Convert(verror.ErrInternal, ctx, err)
			}
			cav = append(cav, thirdParty)
		}
		if len(cav) == 0 {
			// TODO(rthellend,ashankar): the use of unconstrained
			// use is concerning. We should figure out how to get
			// rid of it.
			// Some options:
			//  - have the seeker specify a set of caveats in the
			//    request (and forcefully insert a restrictive one
			//    or fail if the role server thinks that they are
			//    too loose or something).
			//  - have a set of caveats in the config of the role.
			cav = []security.Caveat{security.UnconstrainedUse()}
		}
		b, err := principal.Bless(publicKey, blessWith, ext, cav[0], cav[1:]...)
		if err != nil {
			return security.Blessings{}, verror.Convert(verror.ErrInternal, ctx, err)
		}
		if ret, err = security.UnionOfBlessings(ret, b); err != nil {
			verror.Convert(verror.ErrInternal, ctx, err)
		}
	}
	return ret, nil
}
