// 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()

	server, err := v23.NewServer(ctx)
	if err != nil {
		return fmt.Errorf("failed to create server to receive keys: %v", err)
	}
	defer server.Stop()
	if _, err := server.Listen(v23.GetListenSpec(ctx)); err != nil {
		return fmt.Errorf("failed to setup listening: %v", err)
	}

	service := &recvKeyService{
		env:    env,
		notify: make(chan error),
	}
	if err := server.Serve(recvKeySuffix, service, security.AllowEveryone()); err != nil {
		return fmt.Errorf("failed to setup service for receiving keys: %v", err)
	}

	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() {}
