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

// The following enables go generate to generate the doc.go file.
//go:generate go run $V23_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go .

package main

import (
	"encoding/json"
	"fmt"
	"os"
	"regexp"
	"sort"
	"time"

	"v.io/x/lib/cmdline"
	"v.io/x/lib/set"

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

	"v.io/x/ref/lib/v23cmd"
	_ "v.io/x/ref/runtime/factories/generic"
)

func main() {
	cmdline.HideGlobalFlagsExcept(regexp.MustCompile(`^v23\.namespace\.root$`))
	cmdline.Main(cmdRoot)
}

var (
	flagLongGlob            bool
	flagInsecureGlob        bool
	flagInsecureResolve     bool
	flagInsecureResolveToMT bool
	flagDeleteSubtree       bool
)

func init() {
	cmdGlob.Flags.BoolVar(&flagLongGlob, "l", false, "Long listing format.")
	cmdGlob.Flags.BoolVar(&flagInsecureGlob, "insecure", false, "Insecure mode: May return results from untrusted servers and invoke Glob on untrusted mounttables")
	cmdResolve.Flags.BoolVar(&flagInsecureResolve, "insecure", false, "Insecure mode: May return results from untrusted servers and invoke Resolve on untrusted mounttables")
	cmdResolveToMT.Flags.BoolVar(&flagInsecureResolveToMT, "insecure", false, "Insecure mode: May return results from untrusted servers and invoke Resolve on untrusted mounttables")
	cmdDelete.Flags.BoolVar(&flagDeleteSubtree, "r", false, "Delete all children of the name in addition to the name itself.")
}

var cmdGlob = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runGlob),
	Name:     "glob",
	Short:    "Returns all matching entries from the namespace",
	Long:     "Returns all matching entries from the namespace.",
	ArgsName: "<pattern> [<predicate>]",
	ArgsLong: `
<pattern> is a glob pattern that is matched against all the names below the
specified mount name.

<predicate> is an optional predicate that is matched against all the names
below the specified mount name.
`,
}

func runGlob(ctx *context.T, env *cmdline.Env, args []string) error {
	if expected, got := 1, len(args); expected > got {
		return env.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	if expected, got := 2, len(args); expected < got {
		return env.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	pattern := args[0]
	predicate := ""
	if len(args) > 1 {
		predicate = args[1]
	}

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	ns := v23.GetNamespace(ctx)

	var opts []naming.NamespaceOpt
	if flagInsecureGlob {
		opts = append(opts, options.SkipServerEndpointAuthorization{})
	}
	c, err := ns.GlobWithPredicate(ctx, pattern, predicate, opts...)
	if err != nil {
		ctx.Infof("ns.Glob(%q, %q) failed: %v", pattern, predicate, err)
		return err
	}
	if flagLongGlob {
		// Show all the information we received.
		for res := range c {
			switch v := res.(type) {
			case *naming.GlobReplyEntry:
				fmt.Fprint(env.Stdout, v.Value.Name)
				for _, s := range v.Value.Servers {
					delta := s.Deadline.Time.Sub(time.Now())
					fmt.Fprintf(env.Stdout, " %s (Expires in %d sec)", s.Server, int(delta.Seconds()))
				}
				fmt.Fprintln(env.Stdout)
			case *naming.GlobReplyError:
				fmt.Fprintf(env.Stderr, "Error: %s: %v\n", v.Value.Name, v.Value.Error)
			}
		}
		return nil
	}
	// Show a sorted list of unique names, and any errors.
	resultSet := make(map[string]struct{})
	errors := []*naming.GlobError{}
	for res := range c {
		switch v := res.(type) {
		case *naming.GlobReplyEntry:
			if v.Value.Name != "" {
				resultSet[v.Value.Name] = struct{}{}
			}
		case *naming.GlobReplyError:
			errors = append(errors, &v.Value)
		}
	}
	results := set.String.ToSlice(resultSet)
	sort.Strings(results)
	for _, result := range results {
		fmt.Fprintln(env.Stdout, result)
	}
	for _, err := range errors {
		fmt.Fprintf(env.Stderr, "Error: %s: %v\n", err.Name, err.Error)
	}
	return nil
}

var cmdMount = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runMount),
	Name:     "mount",
	Short:    "Adds a server to the namespace",
	Long:     "Adds server <server> to the namespace with name <name>.",
	ArgsName: "<name> <server> <ttl>",
	ArgsLong: `
<name> is the name to add to the namespace.
<server> is the object address of the server to add.
<ttl> is the TTL of the new entry. It is a decimal number followed by a unit
suffix (s, m, h). A value of 0s represents an infinite duration.
`,
}

func runMount(ctx *context.T, env *cmdline.Env, args []string) error {
	if expected, got := 3, len(args); expected != got {
		return env.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	name := args[0]
	server := args[1]
	ttlArg := args[2]

	ttl, err := time.ParseDuration(ttlArg)
	if err != nil {
		return fmt.Errorf("TTL parse error: %v", err)
	}

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	ns := v23.GetNamespace(ctx)
	if err = ns.Mount(ctx, name, server, ttl); err != nil {
		ctx.Infof("ns.Mount(%q, %q, %s) failed: %v", name, server, ttl, err)
		return err
	}
	fmt.Fprintln(env.Stdout, "Server mounted successfully.")
	return nil
}

var cmdUnmount = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runUnmount),
	Name:     "unmount",
	Short:    "Removes a server from the namespace",
	Long:     "Removes server <server> with name <name> from the namespace.",
	ArgsName: "<name> <server>",
	ArgsLong: `
<name> is the name to remove from the namespace.
<server> is the object address of the server to remove.
`,
}

func runUnmount(ctx *context.T, env *cmdline.Env, args []string) error {
	if expected, got := 2, len(args); expected != got {
		return env.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	name := args[0]
	server := args[1]

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	ns := v23.GetNamespace(ctx)

	if err := ns.Unmount(ctx, name, server); err != nil {
		ctx.Infof("ns.Unmount(%q, %q) failed: %v", name, server, err)
		return err
	}
	fmt.Fprintln(env.Stdout, "Server unmounted successfully.")
	return nil
}

var cmdResolve = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runResolve),
	Name:     "resolve",
	Short:    "Translates a object name to its object address(es)",
	Long:     "Translates a object name to its object address(es).",
	ArgsName: "<name>",
	ArgsLong: "<name> is the name to resolve.",
}

func runResolve(ctx *context.T, env *cmdline.Env, args []string) error {
	if expected, got := 1, len(args); expected != got {
		return env.UsageErrorf("resolve: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	name := args[0]

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	ns := v23.GetNamespace(ctx)

	var opts []naming.NamespaceOpt
	if flagInsecureResolve {
		opts = append(opts, options.SkipServerEndpointAuthorization{})
	}
	me, err := ns.Resolve(ctx, name, opts...)
	if err != nil {
		ctx.Infof("ns.Resolve(%q) failed: %v", name, err)
		return err
	}
	for _, n := range me.Names() {
		fmt.Fprintln(env.Stdout, n)
	}
	return nil
}

var cmdResolveToMT = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runResolveToMT),
	Name:     "resolvetomt",
	Short:    "Finds the address of the mounttable that holds an object name",
	Long:     "Finds the address of the mounttable that holds an object name.",
	ArgsName: "<name>",
	ArgsLong: "<name> is the name to resolve.",
}

func runResolveToMT(ctx *context.T, env *cmdline.Env, args []string) error {
	if expected, got := 1, len(args); expected != got {
		return env.UsageErrorf("resolvetomt: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	name := args[0]

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	ns := v23.GetNamespace(ctx)
	var opts []naming.NamespaceOpt
	if flagInsecureResolveToMT {
		opts = append(opts, options.SkipServerEndpointAuthorization{})
	}
	e, err := ns.ResolveToMountTable(ctx, name, opts...)
	if err != nil {
		ctx.Infof("ns.ResolveToMountTable(%q) failed: %v", name, err)
		return err
	}
	for _, s := range e.Servers {
		fmt.Fprintln(env.Stdout, naming.JoinAddressName(s.Server, e.Name))
	}
	return nil
}

var cmdPermissions = &cmdline.Command{
	Name:  "permissions",
	Short: "Manipulates permissions on an entry in the namespace",
	Long: `
Commands to get and set the permissions on a name - controlling the blessing
names required to resolve the name.

The permissions are provided as an JSON-encoded version of the Permissions type
defined in v.io/v23/security/access/types.vdl.
`,
	Children: []*cmdline.Command{cmdPermissionsGet, cmdPermissionsSet},
}

var cmdPermissionsSet = &cmdline.Command{
	Runner: v23cmd.RunnerFunc(runPermissionsSet),
	Name:   "set",
	Short:  "Sets permissions on a mount name",
	Long: `
Set replaces the permissions controlling usage of a mount name.
`,
	ArgsName: "<name> <permissions>",
	ArgsLong: `
<name> is the name on which permissions are to be set.

<permissions> is the path to a file containing a JSON-encoded Permissions
object (defined in v.io/v23/security/access/types.vdl), or "-" for STDIN.
`,
}

func runPermissionsSet(ctx *context.T, env *cmdline.Env, args []string) error {
	if expected, got := 2, len(args); expected != got {
		return env.UsageErrorf("set: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	name := args[0]
	var perms access.Permissions
	file := os.Stdin
	if args[1] != "-" {
		var err error
		if file, err = os.Open(args[1]); err != nil {
			return err
		}
		defer file.Close()
	}
	if err := json.NewDecoder(file).Decode(&perms); err != nil {
		return err
	}
	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()
	ns := v23.GetNamespace(ctx)
	for {
		_, etag, err := ns.GetPermissions(ctx, name)
		if err != nil && verror.ErrorID(err) != naming.ErrNoSuchName.ID {
			return err
		}
		if err = ns.SetPermissions(ctx, name, perms, etag); verror.ErrorID(err) == verror.ErrBadVersion.ID {
			ctx.Infof("SetPermissions(%q, %q) failed: %v, retrying...", name, etag, err)
			continue
		}
		return err
	}
}

var cmdPermissionsGet = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runPermissionsGet),
	Name:     "get",
	Short:    "Gets permissions on a mount name",
	ArgsName: "<name>",
	ArgsLong: `
<name> is a name in the namespace.
`,
	Long: `
Get retrieves the permissions on the usage of a name.

The output is a JSON-encoded Permissions object (defined in
v.io/v23/security/access/types.vdl).
`,
}

func runPermissionsGet(ctx *context.T, env *cmdline.Env, args []string) error {
	if expected, got := 1, len(args); expected != got {
		return env.UsageErrorf("get: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	name := args[0]
	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	perms, _, err := v23.GetNamespace(ctx).GetPermissions(ctx, name)
	if err != nil {
		return err
	}
	return json.NewEncoder(env.Stdout).Encode(perms)
}

var cmdDelete = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runDelete),
	Name:     "delete",
	Short:    "Deletes a name from the namespace",
	ArgsName: "<name>",
	ArgsLong: "<name> is a name to delete.",
	Long:     "Deletes a name from the namespace.",
}

func runDelete(ctx *context.T, env *cmdline.Env, args []string) error {
	if expected, got := 1, len(args); expected != got {
		return env.UsageErrorf("delete: incorrect number of arguments, expected %d, got %d", expected, got)
	}
	name := args[0]
	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	return v23.GetNamespace(ctx).Delete(ctx, name, flagDeleteSubtree)
}

var cmdRoot = &cmdline.Command{
	Name:  "namespace",
	Short: "resolves and manages names in the Vanadium namespace",
	Long: `
Command namespace resolves and manages names in the Vanadium namespace.

The namespace roots are set from the command line via --v23.namespace.root
command line option or from environment variables that have a name starting
with V23_NAMESPACE, e.g.  V23_NAMESPACE, V23_NAMESPACE_2, V23_NAMESPACE_GOOGLE,
etc.  The command line options override the environment.
`,
	Children: []*cmdline.Command{cmdGlob, cmdMount, cmdUnmount, cmdResolve, cmdResolveToMT, cmdPermissions, cmdDelete},
}
