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

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"time"

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

	"v.io/x/lib/cmdline"
	"v.io/x/lock"
	"v.io/x/lock/locklib"
	"v.io/x/ref/lib/v23cmd"
	_ "v.io/x/ref/runtime/factories/static"
)

const (
	// TODO(ataly): Define these conventions in the README
	recvKeySuffix          = "recvkey"
	lockUserNhPrefix       = "user-"
	lockUserNhGlobPrefix   = "nh/user-"
	vanadiumBlessingPrefix = "dev.v.io/u"
)

var (
	flagSendKeyExpiry time.Duration

	lockNhGlobPrefix = path.Join("nh", locklib.LockNhPrefix)
	cmdScan          = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runScan),
		Name:   "scan",
		Short:  "Scan the neighborhood for lock devices",
		Long: `
Searches for lock devices (both claimed and unclaimed) nearby.
`,
	}
	cmdUsers = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runUsers),
		Name:   "users",
		Short:  "Scan the neighborhood for physical-lock users",
		Long: `
Searches for physical-lock users nearby.
`,
	}
	cmdClaim = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runClaim),
		Name:   "claim",
		Short:  "Claim the specified lock with the provided name",
		Long: `
Claims the specified unclaimed lock with the provided name, and authorizes the
principal executing this command to access the claimed lock.
`,
		ArgsName: "<lock> <name>",
		ArgsLong: `
<lock> is the name of the unclaimed lock.
<name> is a name that you'd like to give to the lock, for example,
"my_front_door" or "123_main_street.
`,
	}
	cmdLock = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runLock),
		Name:   "lock",
		Short:  "Lock the specified lock",
		Long: `
Locks the specified lock.
`,
		ArgsName: "<lock>",
		ArgsLong: `
<lock> is the name of the lock.
`,
	}
	cmdUnlock = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runUnlock),
		Name:   "unlock",
		Short:  "Unlock the specified lock",
		Long: `
Unlocks the specified lock.
`,
		ArgsName: "<lock>",
		ArgsLong: `
<lock> is the name of the lock.
`,
	}
	cmdStatus = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runStatus),
		Name:   "status",
		Short:  "Print the current status of the specified lock",
		Long: `
Prints the current status of the specified lock.
`,
		ArgsName: "<lock>",
		ArgsLong: `
<lock> is the name of the lock.
`,
	}
	cmdListKeys = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runListKeys),
		Name:   "listkeys",
		Short:  "List the set of available keys",
		Long: `
Lists the set of available physical-lock keys and the names of the locks
to which they apply.

Each line of the list is of the form
<lock> <key>

TODO(ataly, ashankar): Also print additional information such as when and
from whom was the key obtained.
`,
	}
	cmdRecvKey = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runRecvKey),
		Name:   "recvkey",
		Short:  "Receive keys to locks sent by another user",
		Long: `
Allows another physical-lock user to send a physical-lock key to this
client.

This command sets up the invoker (this process) to wait for a key to be
sent to this process. On receiving such a key, the process prints out the
key and lock name specified by the sender and asks for the invoker's
permission to save the key.

If permission is granted then the key is saved and the process returns,
otherwise the key is discarded and the command continues to wait for other
keys.
`,
	}
	cmdSendKey = &cmdline.Command{
		Runner: v23cmd.RunnerFunc(runSendKey),
		Name:   "sendkey",
		Short:  "Send keys to other users",
		Long: `
Allows this client to send a physical-lock key to another physical-lock user
present in the neighbordhood (See also: users).

An expiration time can be set on the key via the --for flag.
`,
		ArgsName: "<lock> <user> <category>",
		ArgsLong: `
<lock> is the name of the physical-lock whose key must be sent,
<user> is the physical-lock user to whom the key must be sent, and
<category> is how you'd like to classify the user (e.g., "friend",
"spouse", "colleague", etc.)
`,
	}
)

func runScan(ctx *context.T, env *cmdline.Env, args []string) error {
	ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx))
	if err != nil {
		return err
	}
	defer stop()

	fmt.Println("Scanning for Locks...")
	if err := doGlob(ctx, lockNhGlobPrefix); err != nil {
		return err
	}
	return nil
}

func runUsers(ctx *context.T, env *cmdline.Env, args []string) error {
	ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx))
	if err != nil {
		return err
	}
	defer stop()

	fmt.Println("Scanning for Users...")
	if err := doGlob(ctx, lockUserNhGlobPrefix); err != nil {
		return err
	}
	return nil
}

func doGlob(ctx *context.T, globPrefix string) error {
	globPattern := globPrefix + "*"
	found := make(map[string]bool)
	for {
		ch, err := v23.GetNamespace(ctx).Glob(ctx, globPattern)
		if err != nil {
			return err
		}
		for v := range ch {
			switch entry := v.(type) {
			case *naming.GlobReplyEntry:
				if name, servers := entry.Value.Name, entry.Value.Servers; len(name) != 0 && !found[name] && len(servers) != 0 {
					epStr, _ := naming.SplitAddressName(servers[0].Server)
					ep, err := v23.NewEndpoint(epStr)
					if err != nil {
						continue
					}

					found[name] = true
					printName(name, globPrefix, ep.BlessingNames())
				}
			}
		}
	}
}

func printName(name, prefix string, blessings []string) {
	if !strings.HasPrefix(name, prefix) {
		return
	}
	name = strings.TrimPrefix(name, prefix)

	if len(blessings) != 0 {
		fmt.Printf("%v [owned by %v]\n", name, blessings)
	} else {
		fmt.Printf("%v\n", name)
	}
}

func runClaim(ctx *context.T, env *cmdline.Env, args []string) error {
	if numargs := len(args); numargs != 2 {
		return fmt.Errorf("requires exactly two arguments <lock>, <name>, provided %d", numargs)
	}
	lockName, name := args[0], args[1]

	ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx))
	if err != nil {
		return err
	}
	defer stop()

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()
	// TODO(ataly): We should not skip server endpoint authorization while
	// claiming locks but instead fetch the blessing root of the lock manufacturer
	// from an authoritative source and then appropriately authenticate the server.
	b, err := lock.UnclaimedLockClient(lockObjName(lockName)).Claim(ctx, name, options.SkipServerEndpointAuthorization{})
	if err != nil {
		return err
	}

	p := v23.GetPrincipal(ctx)
	if err := p.AddToRoots(b); err != nil {
		return fmt.Errorf("failed to add (key) blessing (%v) to roots: %v", b, err)
	}
	if _, err := p.BlessingStore().Set(b, security.BlessingPattern(name)); err != nil {
		return fmt.Errorf("failed to set (key) blessing (%v) for peer %v: %v", b, name, err)
	}
	fmt.Printf("Claimed lock: %v as %v and received key: %v\n", lockName, name, b)
	return nil
}

func runLock(ctx *context.T, env *cmdline.Env, args []string) error {
	return updateStatus(ctx, args, lock.Locked)
}

func runUnlock(ctx *context.T, env *cmdline.Env, args []string) error {
	return updateStatus(ctx, args, lock.Unlocked)
}

func updateStatus(ctx *context.T, args []string, status lock.LockStatus) error {
	if numargs := len(args); numargs != 1 {
		return fmt.Errorf("requires exactly one arguments <lock>, provided %d", numargs)
	}
	lockName := args[0]

	ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx))
	if err != nil {
		return err
	}
	defer stop()

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()
	if status == lock.Locked {
		err = lock.LockClient(lockObjName(lockName)).Lock(ctx)
	} else {
		err = lock.LockClient(lockObjName(lockName)).Unlock(ctx)
	}
	if err != nil {
		return err
	}

	fmt.Printf("Updated lock %v to status: %v\n", lockName, status)
	return nil
}

func runStatus(ctx *context.T, env *cmdline.Env, args []string) error {
	if numargs := len(args); numargs != 1 {
		return fmt.Errorf("requires exactly one arguments <lock>, provided %d", numargs)
	}
	lockName := args[0]

	ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx))
	if err != nil {
		return err
	}
	defer stop()

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()
	status, err := lock.LockClient(lockObjName(lockName)).Status(ctx)
	if err != nil {
		return err
	}
	fmt.Printf("lock %v is: %v\n", lockName, status)
	return nil
}

func runListKeys(ctx *context.T, env *cmdline.Env, args []string) error {
	peerBlessings := v23.GetPrincipal(ctx).BlessingStore().PeerBlessings()
	const format = "%-30s   %s (Expires: %s)\n"

	fmt.Printf(format, "Lock", "Key", "<expiry time>")
	for lock, key := range peerBlessings {
		if !isValidLockName(string(lock)) {
			continue
		}
		if !isKeyValidForLock(ctx, key, string(lock)) {
			continue
		}
		var (
			expiresIn string
			now       = time.Now()
		)
		if exp := key.Expiry(); !exp.IsZero() && exp.Before(now) {
			// TODO(ataly): Remove the key from the blessing
			// store.
			continue
		} else if exp.IsZero() {
			expiresIn = "NEVER"
		} else {
			expiresIn = fmt.Sprintf("in %v", exp.Sub(now))
		}
		fmt.Printf(format, lock, key, expiresIn)
	}
	return nil
}

func runRecvKey(ctx *context.T, env *cmdline.Env, args []string) error {
	ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx))
	if err != nil {
		return err
	}
	defer stop()

	service := &recvKeyService{
		env:    env,
		notify: make(chan error),
	}
	_, server, err := v23.WithNewServer(ctx, recvKeySuffix, service, security.AllowEveryone())
	if err != nil {
		return fmt.Errorf("failed to create server to receive keys: %v", err)
	}
	defer server.Stop()
	fmt.Println("Waiting for keys")
	return <-service.notify
}

func runSendKey(ctx *context.T, env *cmdline.Env, args []string) error {
	if numargs := len(args); numargs != 3 {
		return fmt.Errorf("requires exactly three arguments <lock> <user> <category>, provided %d", numargs)
	}
	lockName, user, category := args[0], args[1], args[2]

	ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx))
	if err != nil {
		return err
	}
	defer stop()

	key, err := keyForLock(ctx, lockName)
	if err != nil {
		return err
	}

	fmt.Printf("Sending key %v (extended with %v) to user %v\n", key, category, user)
	client := v23.GetClient(ctx)
	granter := &granter{lockName: lockName, key: key, category: category, expiry: flagSendKeyExpiry, user: user}
	if err := client.Call(ctx, recvKeyObjName(user), "Grant", []interface{}{lockName}, nil, granter); err != nil {
		return fmt.Errorf("failed to send key to %q: %v", user, err)
	}
	return nil
}

// Starts a mounttable server and returns a new context derived from
// the provided one by attaching a namespace instance rooted at the
// started mounttable server.
func withLocalNamespace(ctx *context.T, mtName, nhName string) (*context.T, func(), error) {
	configDir, err := ioutil.TempDir("", "mounttable-config")
	if err != nil {
		return nil, nil, err
	}
	mtName, stopMT, err := locklib.StartMounttable(ctx, configDir, nhName)
	if err != nil {
		os.RemoveAll(configDir)
		return nil, nil, err
	}

	stop := func() {
		stopMT()
		os.RemoveAll(configDir)
	}

	ctx, _, err = v23.WithNewNamespace(ctx, mtName)
	if err != nil {
		stop()
		return nil, nil, err
	}
	return ctx, stop, nil

}

// vUser returns a comma-separated string of user identities obtained
// from the provided blessing names.
//
// For each blessing name, vUser checks if it matches the pattern
// 'vanadiumBlessingPrefix' and if so constructs the user identity by
// stripping off 'vanadiumBlessingPrefix' from the blessing name.
// Otherwise the user identity is simply the blessing name.
//
// In all case, the user identity is converted into a valid neighborhood-name
// by replacing slahes with "@@".
// TODO(ataly): Try to use conventions.GetClientUserIds instead.
func vUser(bNames ...string) string {
	nhFriendly := func(b string) string {
		return strings.Replace(b, security.ChainSeparator, "@@", -1)
	}
	users := make([]string, len(bNames))
	for i, b := range bNames {
		if !security.BlessingPattern(vanadiumBlessingPrefix).MatchedBy(b) {
			users[i] = nhFriendly(b)
			continue
		}
		users[i] = nhFriendly(strings.TrimPrefix(b, vanadiumBlessingPrefix+security.ChainSeparator))
	}
	return strings.Join(users, ",")
}

func lockUserNhName(ctx *context.T) string {
	var (
		principal = v23.GetPrincipal(ctx)
		bNames    []string
	)
	for b, _ := range principal.BlessingsInfo(principal.BlessingStore().Default()) {
		bNames = append(bNames, b)
	}
	return lockUserNhPrefix + vUser(bNames...)
}

func recvKeyObjName(user string) string {
	return path.Join(lockUserNhGlobPrefix+user, recvKeySuffix)
}

func lockObjName(lockName string) string {
	return path.Join(lockNhGlobPrefix+lockName, locklib.LockSuffix)
}

func main() {
	cmdSendKey.Flags.DurationVar(&flagSendKeyExpiry, "for", 0, "Duration of key validity (zero implies no expiration)")
	cmdline.HideGlobalFlagsExcept()
	root := &cmdline.Command{
		Name:  "lock",
		Short: "claim and manage locks",
		Long: `
Command lock claims and manages lock devices.
`,
		Children: []*cmdline.Command{cmdScan, cmdUsers, cmdClaim, cmdLock, cmdUnlock, cmdStatus, cmdListKeys, cmdRecvKey, cmdSendKey},
	}
	cmdline.Main(root)
}

type recvKeyService struct {
	principal security.Principal
	env       *cmdline.Env
	notify    chan error
}

func (r *recvKeyService) confirmRecvKey() bool {
	text, err := readFromStdin(r.env, `Do you want to save this key? (YES to confirm)`)
	if err != nil || strings.ToUpper(text) != "YES" {
		return false
	}
	return true
}

func (r *recvKeyService) Grant(ctx *context.T, call rpc.ServerCall, lockName string) error {
	key := call.GrantedBlessings()
	remoteBlessingNames, _ := security.RemoteBlessingNames(ctx, call.Security())

	fmt.Printf("Received key %v for lock %v from user %v\n", key, lockName, vUser(remoteBlessingNames...))
	if !r.confirmRecvKey() {
		return NewErrKeyRejected(ctx, fmt.Sprintf("%v", key), lockName)
	}

	if err := saveKeyForLock(ctx, key, lockName); err != nil {
		return verror.Convert(verror.ErrInternal, ctx, err)
	}
	fmt.Println("Key successfully saved")
	r.notify <- nil
	return nil
}

type granter struct {
	lockName string
	key      security.Blessings
	category string
	expiry   time.Duration
	user     string
}

func (g *granter) Grant(ctx *context.T, call security.Call) (security.Blessings, error) {
	// Verify that the remote end's blessings encapsulates the
	// same user identity as g.user.
	remoteBlessingNames, _ := security.RemoteBlessingNames(ctx, call)
	authorized := false
	for _, b := range remoteBlessingNames {
		if vUser(b) == g.user {
			authorized = true
		}
	}
	if !authorized {
		return security.Blessings{}, fmt.Errorf("remote end presented blessings %v, want a blessing for user %v", remoteBlessingNames, g.user)
	}

	peerPattern := security.BlessingPattern(g.lockName)
	onlyThisLockCav, err := security.NewCaveat(security.PeerBlessingsCaveat, []security.BlessingPattern{peerPattern})
	if err != nil {
		return security.Blessings{}, fmt.Errorf("failed to create peer blessings caveat for key: %v", err)
	}

	caveats := []security.Caveat{onlyThisLockCav}
	if g.expiry != 0 {
		expiryCav, err := security.NewExpiryCaveat(time.Now().Add(g.expiry))
		if err != nil {
			return security.Blessings{}, fmt.Errorf("failed to create expiration caveat for key: %v", err)
		}
		caveats = append(caveats, expiryCav)
	}
	return call.LocalPrincipal().Bless(call.RemoteBlessings().PublicKey(), g.key, g.category, caveats[0], caveats[1:]...)
}

func (*granter) RPCCallOpt() {}
