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

import (
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/security"
	"v.io/v23/vdl"
)

// DischargeRefreshFraction determines how early before their expiration
// time we refresh discharges.  A value of 0.5 means we refresh when it
// is only half way to is expiration time.
const DischargeRefreshFraction = 0.5

// If this is attached to the context, we will not fetch discharges.
// We use this to prevent ourselves from fetching discharges in the
// process of fetching discharges, thus creating an infinite loop.
type skipDischargesKey struct{}

type updateResult struct {
	refreshTime time.Time
	discharge   security.Discharge
	done        bool
}

type work struct {
	caveat  security.Caveat
	impetus security.DischargeImpetus
}

// PrepareDischarges retrieves the caveat discharges required for using blessings
// at server. The discharges are either found in the dischargeCache, in the call
// options, or requested from the discharge issuer indicated on the caveat.
// Note that requesting a discharge is an rpc call, so one copy of this
// function must be able to successfully terminate while another is blocked.
// PrepareDischarges also returns a refreshTime, which is the time at which
// PrepareDischarges should be called again (or zero if none of the discharges
// expire).
func PrepareDischarges(
	ctx *context.T,
	blessings security.Blessings,
	impetus security.DischargeImpetus) (map[string]security.Discharge, time.Time) {
	tpCavs := blessings.ThirdPartyCaveats()
	if len(tpCavs) == 0 {
		return nil, time.Time{}
	}
	// We only want to send the impetus information we really need for each
	// discharge.
	todo := make(map[string]work, len(tpCavs))
	for _, cav := range tpCavs {
		if tp := cav.ThirdPartyDetails(); tp != nil {
			todo[tp.ID()] = work{cav, filteredImpetus(tp.Requirements(), impetus)}
		}
	}
	//Since there may be dependencies in the caveats, we keep retrying
	//until either all discharges can be fetched or no new discharges
	//are fetched.
	var minRefreshTime time.Time
	ch := make(chan *updateResult, len(tpCavs))
	ret := make(map[string]security.Discharge, len(tpCavs))
	for {
		want := len(todo)
		now := time.Now()
		for _, w := range todo {
			updateDischarge(ctx, now, w.impetus, w.caveat, ch)
		}
		got := 0
		for i := 0; i < want; i++ {
			res := <-ch
			id := res.discharge.ID()
			ret[id] = res.discharge
			if res.done {
				minRefreshTime = minTime(minRefreshTime, res.refreshTime)
				delete(todo, id)
				got++
			}
		}
		if got == want {
			return ret, minRefreshTime
		}
		if got == 0 {
			return ret, minTime(minRefreshTime, time.Now().Add(time.Minute))
		}
	}
}

func updateDischarge(
	ctx *context.T,
	now time.Time,
	impetus security.DischargeImpetus,
	caveat security.Caveat,
	out chan<- *updateResult) {
	bstore := v23.GetPrincipal(ctx).BlessingStore()
	dis, ct := bstore.Discharge(caveat, impetus)
	if skip, _ := ctx.Value(skipDischargesKey{}).(bool); skip {
		// We can't fetch discharges while making a call to fetch a discharge.
		// Just go with what we have in the cache.
		out <- &updateResult{done: true, discharge: dis}
		return
	}
	if rt := refreshTime(dis, ct); dis.ID() != "" && (now.Before(rt) || rt.IsZero()) {
		// The cached value is still fresh, just return it.
		out <- &updateResult{done: true, discharge: dis, refreshTime: rt}
		return
	}
	// discharge in blessing store either doesn't exist or may be stale,
	// refresh via RPC.
	go func() {
		tp := caveat.ThirdPartyDetails()
		ctx = context.WithValue(ctx, skipDischargesKey{}, true)
		var newDis security.Discharge
		args, res := []interface{}{caveat, impetus}, []interface{}{&newDis}
		ctx.VI(3).Infof("Fetching discharge for %v", tp)
		if err := v23.GetClient(ctx).Call(ctx, tp.Location(), "Discharge", args, res); err != nil {
			ctx.VI(3).Infof("Discharge fetch for %v failed: %v", tp, err)
			out <- &updateResult{discharge: dis}
		}
		bstore.CacheDischarge(newDis, caveat, impetus)
		out <- &updateResult{done: true, discharge: newDis, refreshTime: refreshTime(newDis, time.Now())}
	}()
}

// filteredImpetus returns a copy of 'before' after removing any values that are not required as per 'r'.
func filteredImpetus(r security.ThirdPartyRequirements, before security.DischargeImpetus) (after security.DischargeImpetus) {
	if r.ReportServer && len(before.Server) > 0 {
		after.Server = make([]security.BlessingPattern, len(before.Server))
		for i := range before.Server {
			after.Server[i] = before.Server[i]
		}
	}
	if r.ReportMethod {
		after.Method = before.Method
	}
	if r.ReportArguments && len(before.Arguments) > 0 {
		after.Arguments = make([]*vdl.Value, len(before.Arguments))
		for i := range before.Arguments {
			after.Arguments[i] = vdl.CopyValue(before.Arguments[i])
		}
	}
	return
}

func refreshTime(dis security.Discharge, cacheTime time.Time) time.Time {
	expiry := dis.Expiry()
	if expiry.IsZero() {
		return time.Time{}
	}
	if cacheTime.IsZero() {
		// If we don't know the cache time, just try to refresh within a minute of
		// the expiry time.
		return expiry.Add(-time.Minute)
	}
	lifetime := expiry.Sub(cacheTime)
	return expiry.Add(-time.Duration(float64(lifetime) * DischargeRefreshFraction))
}

func minTime(a, b time.Time) time.Time {
	if a.IsZero() || (!b.IsZero() && b.Before(a)) {
		return b
	}
	return a
}
