// Copyright 2016 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 commands

import (
	"fmt"
	"strings"

	"v.io/v23/context"
	"v.io/v23/security"
	"v.io/v23/security/access"
	wire "v.io/v23/services/syncbase"
	"v.io/v23/syncbase"
	sbUtil "v.io/v23/syncbase/util"
	"v.io/x/lib/cmdline"
	"v.io/x/ref/cmd/sb/dbutil"
)

var cmdAcl = &cmdline.Command{
	Name:     "acl",
	Short:    "Read or mutate the ACLs",
	Long:     `Read or mutate the ACLs`,
	Children: []*cmdline.Command{cmdAclGet, cmdAclAdd, cmdAclRm, cmdAclDump},
}

var (
	flagTarget     string
	flagCollection string
)

func init() {
	cmdAcl.Flags.StringVar(&flagTarget, "target", "db", "The access controller type to act on (service, db, collection).")
	cmdAcl.Flags.StringVar(&flagCollection, "collection", "", "The collection to act on. (note: requires -target=collection)")
}

func updatePerms(ctx *context.T, db syncbase.Database, env *cmdline.Env, callback func(access.Permissions) (access.Permissions, error)) error {
	switch flagTarget {
	case "service", "db", "database":
		var ac sbUtil.AccessController
		if flagTarget == "service" {
			ac = dbutil.GetService()
		} else {
			ac = db
		}

		perms, version, err := ac.GetPermissions(ctx)
		if err != nil {
			return err
		}

		if perms, err = callback(perms); err != nil {
			return err
		}

		if perms != nil {
			if err := ac.SetPermissions(ctx, perms, version); err != nil {
				return fmt.Errorf("error setting permissions: %q", err)
			}
		}
		return nil
	case "collection":
		bdb, err := db.BeginBatch(ctx, wire.BatchOptions{})
		if err != nil {
			return err
		}
		defer bdb.Abort(ctx)

		collection := bdb.Collection(ctx, flagCollection)
		perms, err := collection.GetPermissions(ctx)
		if err != nil {
			return err
		}

		if perms, err = callback(perms); err != nil {
			return err
		}

		if perms != nil {
			if err = collection.SetPermissions(ctx, perms); err != nil {
				return err
			}

			return bdb.Commit(ctx)
		}
		return nil
	default:
		return env.UsageErrorf("target %s not recognized", flagTarget)
	}

	return nil
}

var cmdAclGet = &cmdline.Command{
	Name:     "get",
	Short:    "Read a blessing's permissions",
	Long:     "Read a blessing's permissions",
	ArgsName: "<blessing>",
	ArgsLong: `
<blessing> is the blessing to check permissions for.
`,
	Runner: SbRunner(runAclGet),
}

func runAclGet(ctx *context.T, db syncbase.Database, env *cmdline.Env, args []string) error {
	if got := len(args); got != 1 {
		return env.UsageErrorf("get: expected 1 arg, got %d", got)
	}

	blessing := args[0]
	return updatePerms(ctx, db, env,
		func(perms access.Permissions) (access.Permissions, error) {
			// Pretty-print the groups that blessing is in
			var groupsIn []string
			for groupName, acl := range perms {
				for _, b := range acl.In {
					if b == security.BlessingPattern(blessing) {
						groupsIn = append(groupsIn, groupName)
						break
					}
				}
			}
			fmt.Printf("[%s]\n", strings.Join(groupsIn, ", "))

			// Pretty-print the groups that blessing is blacklisted from
			var groupsNotIn []string
			for groupName, acl := range perms {
				for _, b := range acl.NotIn {
					if b == blessing {
						groupsNotIn = append(groupsNotIn, groupName)
						break
					}
				}
			}
			fmt.Printf("![%s]\n", strings.Join(groupsNotIn, ", "))

			return nil, nil
		},
	)
}

var cmdAclAdd = &cmdline.Command{
	Name:     "add",
	Short:    "Add blessing to groups",
	Long:     "Add blessing to groups",
	ArgsName: "(<blessing> [!]<tag>(,[!]<tag>)* )+",
	ArgsLong: `
The args are sequential pairs of the form "<blessing> <taglist>"
A taglist is made up of a series of comma-separated tags.
The optional preface "!" puts the blessing in the blacklist instead of the whitelist.
Note that the pair "dev.v.io:u:foo@google.com bar,baz,!bar" is legal.
In such a case the blessing will be added to both the blacklist and the whitelist,
with the blacklist overriding the whitelist.
`,
	Runner: SbRunner(runAclAdd),
}

func runAclAdd(ctx *context.T, db syncbase.Database, env *cmdline.Env, args []string) error {
	if len(args) == 0 {
		return env.UsageErrorf("add: expected arguments")
	}

	userToPerms, err := parseAccessList(args)
	if err != nil {
		return env.UsageErrorf("add: error parsing access list: %q", err)
	}

	return updatePerms(ctx, db, env,
		func(perms access.Permissions) (access.Permissions, error) {
			for blessing, tags := range userToPerms {
				bp := security.BlessingPattern(blessing)
				perms = perms.Add(bp, tags.in...)
				perms = perms.Blacklist(blessing, tags.out...)
			}
			return perms, nil
		},
	)
}

var cmdAclRm = &cmdline.Command{
	Name:     "rm",
	Short:    "Remove specific permissions from the acl.",
	Long:     "Remove specific permissions from the acl.",
	ArgsName: "(<blessing> <tag>(,<tag>)* )+",
	ArgsLong: `
The args are sequential pairs of the form "<blessing> <taglist>"
A taglist is made up of a series of comma-separated tags.
rm removes all references to each <blessing> from all of the tags.
`,
	Runner: SbRunner(runAclRm),
}

func runAclRm(ctx *context.T, db syncbase.Database, env *cmdline.Env, args []string) error {
	if len(args) == 0 {
		return env.UsageErrorf("rm: expected arguments")
	}

	userToPerms, err := parseAccessList(args)
	if err != nil {
		return env.UsageErrorf("rm: failed to parse access list: %q", err)
	}

	return updatePerms(ctx, db, env,
		func(perms access.Permissions) (access.Permissions, error) {
			for blessing, tags := range userToPerms {
				perms = perms.Clear(blessing, tags.in...)
			}
			return perms, nil
		},
	)
}

var cmdAclDump = &cmdline.Command{
	Name:   "dump",
	Short:  "Pretty-print the whole acl",
	Long:   "Pretty-print the whole acl",
	Runner: SbRunner(runAclDump),
}

func runAclDump(ctx *context.T, db syncbase.Database, env *cmdline.Env, args []string) error {
	return updatePerms(ctx, db, env,
		func(perms access.Permissions) (access.Permissions, error) {
			fmt.Println("map[")
			for tag, acl := range perms {
				fmt.Printf("\t%s: %v\n", tag, acl)
			}
			fmt.Println("]")
			return nil, nil
		},
	)
}

type userTags struct {
	in  []string
	out []string
}

// parseAccessList returns a map from blessing patterns to structs containing lists
// of tags which the pattern is white/blacklisted on
func parseAccessList(args []string) (map[string]userTags, error) {
	if got := len(args); got%2 != 0 {
		return nil, fmt.Errorf("incorrect number of arguments %d, must be even", got)
	}

	userToTags := make(map[string]userTags)
	for i := 0; i < len(args); i += 2 {
		tags, err := parseAccessTags(args[i+1])
		if err != nil {
			return nil, err
		}
		userToTags[args[i]] = tags
	}

	return userToTags, nil
}

// parseAccessTags returns two lists of tags, the first being tags which have
// whitelisted the blessing, and the second being tags which have blacklisted it.
func parseAccessTags(input string) (tags userTags, err error) {
	fields := strings.Split(input, ",")
	for _, tag := range fields {
		blacklist := strings.HasPrefix(tag, "!")
		if blacklist {
			tag = tag[1:]
		}
		if len(tag) == 0 {
			return userTags{}, fmt.Errorf("empty access tag in %q", input)
		}

		if blacklist {
			tags.out = append(tags.out, tag)
		} else {
			tags.in = append(tags.in, tag)
		}
	}

	return
}
