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

// TODO(sadovsky): Check Resolve access on parent where applicable. Relatedly,
// convert ErrNoExist and ErrNoAccess to ErrNoExistOrNoAccess where needed to
// preserve privacy.

import (
	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/security/access"
	"v.io/v23/services/groups"
	"v.io/v23/verror"
	"v.io/x/lib/set"
	"v.io/x/ref/services/groups/internal/store"
)

type group struct {
	name string
	m    *manager
}

var _ groups.GroupServerMethods = (*group)(nil)

// TODO(sadovsky): Reserve buckets for users.
func (g *group) Create(ctx *context.T, call rpc.ServerCall, perms access.Permissions, entries []groups.BlessingPatternChunk) error {
	// Perform Permissions check.
	// TODO(sadovsky): Enable this Permissions check and acquire a lock on the
	// group server Permissions.
	if false {
		if err := g.authorize(ctx, call.Security(), g.m.perms); err != nil {
			return err
		}
	}
	if perms == nil {
		perms = access.Permissions{}
		blessings, _ := security.RemoteBlessingNames(ctx, call.Security())
		if len(blessings) == 0 {
			// The blessings presented by the caller do not give it a name for this
			// operation. We could create a world-accessible group, but it seems safer
			// to return an error.
			return groups.NewErrNoBlessings(ctx)
		}
		for _, tag := range access.AllTypicalTags() {
			for _, b := range blessings {
				perms.Add(security.BlessingPattern(b), string(tag))
			}
		}
	}
	entrySet := map[groups.BlessingPatternChunk]struct{}{}
	for _, v := range entries {
		entrySet[v] = struct{}{}
	}
	gd := groupData{Perms: perms, Entries: entrySet}
	if err := g.m.st.Insert(g.name, gd); err != nil {
		// TODO(sadovsky): We are leaking the fact that this group exists. If the
		// client doesn't have access to this group, we should probably return an
		// opaque error. (Reserving buckets for users will help.)
		if verror.ErrorID(err) == store.ErrKeyExists.ID {
			return verror.New(verror.ErrExist, ctx, g.name)
		}
		return verror.New(verror.ErrInternal, ctx, err)
	}
	return nil
}

func (g *group) Delete(ctx *context.T, call rpc.ServerCall, version string) error {
	if err := g.readModifyWrite(ctx, call.Security(), version, func(gd *groupData, versionSt string) error {
		return g.m.st.Delete(g.name, versionSt)
	}); err != nil && verror.ErrorID(err) != verror.ErrNoExist.ID {
		return err
	}
	return nil
}

func (g *group) Add(ctx *context.T, call rpc.ServerCall, entry groups.BlessingPatternChunk, version string) error {
	return g.update(ctx, call.Security(), version, func(gd *groupData) {
		if gd.Entries == nil {
			gd.Entries = map[groups.BlessingPatternChunk]struct{}{}
		}
		gd.Entries[entry] = struct{}{}
	})
}

func (g *group) Remove(ctx *context.T, call rpc.ServerCall, entry groups.BlessingPatternChunk, version string) error {
	return g.update(ctx, call.Security(), version, func(gd *groupData) {
		delete(gd.Entries, entry)
	})
}

func (g *group) Get(ctx *context.T, call rpc.ServerCall, req groups.GetRequest, reqVersion string) (groups.GetResponse, string, error) {
	gd, resVersion, err := g.getInternal(ctx, call.Security())
	if err != nil {
		return groups.GetResponse{}, "", err
	}

	// If version is set and matches the Group's current version,
	// send an empty response (the equivalent of "HTTP 304 Not Modified").
	if reqVersion == resVersion {
		return groups.GetResponse{}, resVersion, nil
	}

	return groups.GetResponse{Entries: gd.Entries}, resVersion, nil
}

func (g *group) Relate(ctx *context.T, call rpc.ServerCall, blessings map[string]struct{}, hint groups.ApproximationType, reqVersion string, visitedGroups map[string]struct{}) (map[string]struct{}, []groups.Approximation, string, error) {
	gd, resVersion, err := g.getInternal(ctx, call.Security())
	if err != nil {
		return nil, nil, "", err
	}

	// If version is set and matches the Group's current version,
	// send an empty response (the equivalent of "HTTP 304 Not Modified").
	if reqVersion == resVersion {
		return nil, nil, resVersion, nil
	}

	remainder := make(map[string]struct{})
	var approximations []groups.Approximation
	for p := range gd.Entries {
		rem, apprxs := groups.Match(ctx, security.BlessingPattern(p), hint, visitedGroups, blessings)
		set.String.Union(remainder, rem)
		approximations = append(approximations, apprxs...)
	}

	return remainder, approximations, resVersion, nil
}

func (g *group) SetPermissions(ctx *context.T, call rpc.ServerCall, perms access.Permissions, version string) error {
	return g.update(ctx, call.Security(), version, func(gd *groupData) {
		gd.Perms = perms
	})
}

func (g *group) GetPermissions(ctx *context.T, call rpc.ServerCall) (perms access.Permissions, version string, err error) {
	gd, version, err := g.getInternal(ctx, call.Security())
	if err != nil {
		return nil, "", err
	}
	return gd.Perms, version, nil
}

////////////////////////////////////////
// Internal helpers

// Returns a VDL-compatible error.
func (g *group) authorize(ctx *context.T, call security.Call, perms access.Permissions) error {
	//auth, _ := access.TypicalTagTypePermissionsAuthorizer(perms)
	auth := access.TypicalTagTypePermissionsAuthorizer(perms)
	if err := auth.Authorize(ctx, call); err != nil {
		return verror.New(verror.ErrNoAccess, ctx, err)
	}
	return nil
}

// Returns a VDL-compatible error. Performs access check.
func (g *group) getInternal(ctx *context.T, call security.Call) (gd groupData, version string, err error) {
	version, err = g.m.st.Get(g.name, &gd)
	if err != nil {
		if verror.ErrorID(err) == store.ErrUnknownKey.ID {
			return groupData{}, "", verror.New(verror.ErrNoExist, ctx, g.name)
		}
		return groupData{}, "", verror.New(verror.ErrInternal, ctx, err)
	}
	if err := g.authorize(ctx, call, gd.Perms); err != nil {
		return groupData{}, "", err
	}
	return gd, version, nil
}

// Returns a VDL-compatible error. Performs access check.
func (g *group) update(ctx *context.T, call security.Call, version string, fn func(gd *groupData)) error {
	return g.readModifyWrite(ctx, call, version, func(gd *groupData, versionSt string) error {
		fn(gd)
		return g.m.st.Update(g.name, *gd, versionSt)
	})
}

// Returns a VDL-compatible error. Performs access check.
// fn should perform the "modify, write" part of "read, modify, write", and
// should return a Store error.
func (g *group) readModifyWrite(ctx *context.T, call security.Call, version string, fn func(gd *groupData, versionSt string) error) error {
	// Transaction retry loop.
	for i := 0; i < 3; i++ {
		gd, versionSt, err := g.getInternal(ctx, call)
		if err != nil {
			return err
		}
		// Fail early if possible.
		if version != "" && version != versionSt {
			return verror.NewErrBadVersion(ctx)
		}
		if err := fn(&gd, versionSt); err != nil {
			if verror.ErrorID(err) == verror.ErrBadVersion.ID {
				// Retry on version error if the original version was empty.
				if version != "" {
					return err
				}
			} else {
				// Abort on non-version error.
				return verror.New(verror.ErrInternal, ctx, err)
			}
		} else {
			return nil
		}
	}
	return groups.NewErrExcessiveContention(ctx)
}
