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

import (
	"encoding/json"
	"io"
	"os"
	"reflect"
	"sort"
	"strconv"
	"strings"

	"v.io/v23/context"
	"v.io/v23/security"
	"v.io/v23/security/access"
	"v.io/v23/services/mounttable"
	"v.io/v23/verror"
	"v.io/x/lib/vlog"
)

// Blessings can't include a comma so we use them in made up user ids.  The following distinctions are
// made so that we can account for them differently.
const localUser = ",LOCAL,"     // a client that has our public key but no blessing from which we can extract a user name
const blessedUser = ",BLESSED," // a client with blessings we trust but from which we can't extract a user name
const unknownUser = ",UNKNOWN," // a client which presents no blessing we trust

// VersionedPermissions associates a Version with a Permissions
type VersionedPermissions struct {
	V int32
	P access.Permissions
}

func NewVersionedPermissions() *VersionedPermissions {
	return &VersionedPermissions{P: make(access.Permissions)}
}

// Set sets the Permissions iff Version matches the current Version.  If the set happens, the Version is advanced.
// If b is nil, this creates a new VersionedPermissions.
func (b *VersionedPermissions) Set(ctx *context.T, verstr string, perm access.Permissions) (*VersionedPermissions, error) {
	if b == nil {
		b = new(VersionedPermissions)
	}
	if len(verstr) > 0 {
		gen, err := strconv.ParseInt(verstr, 10, 32)
		if err != nil {
			return b, verror.NewErrBadVersion(ctx)
		}
		if gen >= 0 && int32(gen) != b.V {
			return b, verror.NewErrBadVersion(ctx)
		}
	}
	b.P = perm
	// Increment with possible wrap.
	b.V++
	if b.V < 0 {
		b.V = 0
	}
	return b, nil
}

// Get returns the current Version and Permissions.
func (b *VersionedPermissions) Get() (string, access.Permissions) {
	if b == nil {
		return "", nil
	}
	return strconv.FormatInt(int64(b.V), 10), b.P
}

// AccessListForTag returns the current access list for the given tag.
func (b *VersionedPermissions) AccessListForTag(tag string) (access.AccessList, bool) {
	al, exists := b.P[tag]
	return al, exists
}

// Copy copies the receiver.
func (b *VersionedPermissions) Copy() *VersionedPermissions {
	nt := new(VersionedPermissions)
	nt.P = b.P.Copy()
	nt.V = b.V
	return nt
}

// Add adds the blessing pattern to the tag in the reciever.
func (b *VersionedPermissions) Add(pattern security.BlessingPattern, tag string) {
	b.P.Add(pattern, tag)
}

// parsePermFile reads a file and parses the contained permissions.
func (mt *mountTable) parsePermFile(path string) error {
	vlog.VI(2).Infof("parsePermFile(%s)", path)
	if path == "" {
		return nil
	}
	// A map from node name to permissions.
	var pm map[string]access.Permissions
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	decoder := json.NewDecoder(f)
	for {
		if err = decoder.Decode(&pm); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		// Sort the map shortest key first.  That way configs for nodes higher up in the
		// name tree happen first ensuring that lower nodes correctly inherit permissions.
		var keys []string
		for name := range pm {
			keys = append(keys, name)
		}
		sort.Strings(keys)
		for _, name := range keys {
			perms := pm[name]
			var elems []string
			isPattern := false

			// The configuration file allows patterns and also will cause the superuser to
			// be set to the root's administrator.
			if len(name) == 0 {
				// If the config file has is an Admin tag on the root AccessList, the
				// list of Admin users is the equivalent of a super user for
				// the whole table.  Later SetPermissions do not update the set
				// of super users.
				if bp, exists := perms[string(mounttable.Admin)]; exists {
					mt.superUsers = bp
				}
			} else {
				// AccessList templates terminate with a %% element.  These are very
				// constrained matches, i.e., the trailing element of the name
				// is copied into every %% in the AccessList.
				elems = strings.Split(name, "/")
				if elems[len(elems)-1] == templateVar {
					isPattern = true
					elems = elems[:len(elems)-1]
				}
			}

			// Create name and add the Permissions map to it.
			n, err := mt.findNode(nil, nil, elems, true, nil, nil)
			if n != nil || err == nil {
				vlog.VI(2).Infof("added perms %v to %s", perms, name)
				if isPattern {
					n.permsTemplate = perms
					// Save the pattern prefix as a prefix describing a user.
					prefix := strings.Join(elems[:len(elems)-1], "/")
					if prefix != "" {
						prefix += "/"
					}
					mt.userPrefixes = append(mt.userPrefixes, prefix)
				} else {
					n.vPerms, _ = n.vPerms.Set(nil, "", perms)
					n.explicitPermissions = true
				}
			}
			n.parent.Unlock()
			n.Unlock()
		}
	}
	return nil
}

// pickCreator returns a string matching the blessing of the user performing the creation.  We do this using
// the user prefixes found when parsing the config.  Eventually we may need a better way to define user
// prefixes.
//
// TODO(p): readdress this argument after we have some experience with real users.
func (mt *mountTable) pickCreator(ctx *context.T, call security.Call) string {
	// For each blessing, look for one that has a matching user prefix.  The creator is the perfix
	// plus one more element.
	//
	// The prefixes themselves come from the templates in the config that constrain node names to
	// match the user.
	blessings, _ := security.RemoteBlessingNames(ctx, call)
	for _, b := range blessings {
		for _, p := range mt.userPrefixes {
			sb := string(b)
			if !strings.HasPrefix(sb, p) {
				continue
			}
			suffix := strings.TrimPrefix(sb, p)
			elems := strings.Split(suffix, "/")
			return p + elems[0]
		}
	}
	if ctx == nil || call == nil {
		return localUser
	}
	if l, r := call.LocalBlessings().PublicKey(), call.RemoteBlessings().PublicKey(); l != nil && reflect.DeepEqual(l, r) {
		return localUser
	}
	if len(blessings) > 0 {
		return blessedUser
	}
	return unknownUser
}
