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

import (
	"bytes"

	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/rpc"
	"v.io/v23/security/access"
	wire "v.io/v23/services/syncbase"
	"v.io/v23/services/watch"
	pubutil "v.io/v23/syncbase/util"
	"v.io/v23/verror"
	"v.io/v23/vom"
	"v.io/x/ref/services/syncbase/common"
	"v.io/x/ref/services/syncbase/server/filter"
	"v.io/x/ref/services/syncbase/server/interfaces"
	"v.io/x/ref/services/syncbase/store"
	"v.io/x/ref/services/syncbase/store/watchable"
)

// GetResumeMarker implements the wire.DatabaseWatcher interface.
func (d *database) GetResumeMarker(ctx *context.T, call rpc.ServerCall, bh wire.BatchHandle) (watch.ResumeMarker, error) {
	allowGetResumeMarker := wire.AllDatabaseTags

	if !d.exists {
		return nil, verror.New(verror.ErrNoExist, ctx, d.id)
	}
	var res watch.ResumeMarker
	impl := func(sntx store.SnapshotOrTransaction) (err error) {
		// Check permissions on Database.
		if _, err := common.GetPermsWithAuth(ctx, call, d, allowGetResumeMarker, sntx); err != nil {
			return err
		}
		res, err = watchable.GetResumeMarker(sntx)
		return err
	}
	if err := d.runWithExistingBatchOrNewSnapshot(ctx, bh, impl); err != nil {
		return nil, err
	}
	return res, nil
}

// WatchGlob implements the wire.DatabaseWatcher interface.
func (d *database) WatchGlob(ctx *context.T, call watch.GlobWatcherWatchGlobServerCall, req watch.GlobRequest) error {
	// Database permissions checked in d.watchWithFilter and d.processLogBatch.
	sender := &watchBatchSender{
		send: call.SendStream().Send,
	}
	gf, err := filter.NewGlobFilter(req.Pattern)
	if err != nil {
		return verror.New(verror.ErrBadArg, ctx, err)
	}
	return d.watchWithFilter(ctx, call, sender, req.ResumeMarker, gf)
}

// WatchPatterns implements the wire.DatabaseWatcher interface.
func (d *database) WatchPatterns(ctx *context.T, call wire.DatabaseWatcherWatchPatternsServerCall, resumeMarker watch.ResumeMarker, patterns []wire.CollectionRowPattern) error {
	// Database permissions checked in d.watchWithFilter and d.processLogBatch.
	sender := &watchBatchSender{
		send: call.SendStream().Send,
	}
	mpf, err := filter.NewMultiPatternFilter(patterns)
	if err != nil {
		return verror.New(verror.ErrBadArg, ctx, err)
	}
	return d.watchWithFilter(ctx, call, sender, resumeMarker, mpf)
}

// watchWithFilter sends the initial state (if necessary) and watch events,
// filtered using watchFilter, to the caller using sender.
func (d *database) watchWithFilter(ctx *context.T, call rpc.ServerCall, sender *watchBatchSender, resumeMarker watch.ResumeMarker, watchFilter filter.CollectionRowFilter) error {
	allowWatchDbStart := []access.Tag{access.Read}

	if !d.exists {
		return verror.New(verror.ErrNoExist, ctx, d.id)
	}
	initImpl := func(sntx store.SnapshotOrTransaction) error {
		// Check permissions on Database.
		if _, err := common.GetPermsWithAuth(ctx, call, d, allowWatchDbStart, sntx); err != nil {
			return err
		}
		needInitialState := len(resumeMarker) == 0
		needResumeMarker := needInitialState || bytes.Equal(resumeMarker, []byte("now"))
		// Get the resume marker if necessary.
		if needResumeMarker {
			var err error
			if resumeMarker, err = watchable.GetResumeMarker(sntx); err != nil {
				return err
			}
		}
		// Send the root update to notify the client that watch has started.
		rootChangeState := watch.InitialStateSkipped
		if needInitialState {
			rootChangeState = watch.Exists
		}
		if err := sender.addChange(
			"",
			rootChangeState,
			&wire.StoreChange{
				FromSync: false,
			}); err != nil {
			return err
		}
		// Send initial state if necessary.
		if needInitialState {
			if err := d.scanInitialState(ctx, call, sender, sntx, watchFilter); err != nil {
				return err
			}
		}
		// Finalize initial state or root update batch.
		return sender.finishBatch(resumeMarker)
	}
	if err := store.RunWithSnapshot(d.st, initImpl); err != nil {
		return err
	}
	return d.watchUpdates(ctx, call, sender, resumeMarker, watchFilter)
}

// scanInitialState sends the initial state of all matching and accessible
// collections and rows in the database. Checks access on collections, but
// not on database.
// Note: Assumes Read perms on database. Careful if supporting RPCs requiring
// only Resolve.
// TODO(ivanpi): Abstract out multi-scan for scan and possibly query support.
// TODO(ivanpi): Use watch pattern prefixes to optimize scan ranges.
func (d *database) scanInitialState(ctx *context.T, call rpc.ServerCall, sender *watchBatchSender, sntx store.SnapshotOrTransaction, watchFilter filter.CollectionRowFilter) error {
	// Scan matching and accessible collections.
	// TODO(ivanpi): Collection scan order not alphabetical.
	cxIt := sntx.Scan(common.ScanPrefixArgs(common.CollectionPermsPrefix, ""))
	defer cxIt.Cancel()
	cxKey, cxPermsValue := []byte{}, []byte{}
	for cxIt.Advance() {
		cxKey, cxPermsValue = cxIt.Key(cxKey), cxIt.Value(cxPermsValue)
		// Database permissions for Watch ensure that the user is always allowed
		// to know that a collection exists.
		cxId, err := common.ParseCollectionPermsKey(string(cxKey))
		if err != nil {
			return verror.New(verror.ErrInternal, ctx, err)
		}
		// Filter out unnecessary collections.
		if !watchFilter.CollectionMatches(cxId) {
			continue
		}
		// Send collection info.
		var cxPerms interfaces.CollectionPerms
		if err := vom.Decode(cxPermsValue, &cxPerms); err != nil {
			return verror.NewErrInternal(ctx) // no detailed error for cxPerms before filtering cxInfo
		}
		cxInfo := collectionInfoFromPerms(ctx, call, cxPerms.GetPerms())
		cxInfoAsRawBytes, err := vom.RawBytesFromValue(cxInfo)
		if err != nil {
			return verror.New(verror.ErrInternal, ctx, err)
		}
		if err := sender.addChange(
			pubutil.EncodeId(cxId),
			watch.Exists,
			&wire.StoreChange{
				Value: cxInfoAsRawBytes,
				// Note: FromSync cannot be reconstructed from scan.
				FromSync: false,
			}); err != nil {
			return err
		}
		// Filter out rows with no read access.
		// TODO(ivanpi): Collection scan already gets perms, optimize?
		// TODO(ivanpi): Check service and database resolve only once.
		c := &collectionReq{
			id: cxId,
			d:  d,
		}
		if _, err := common.GetPermsWithAuth(ctx, call, c, []access.Tag{access.Read}, sntx); err != nil {
			if verror.ErrorID(err) == verror.ErrNoAccess.ID {
				// Skip sending rows if the collection is inaccessible. Caller can see
				// from collection info that they have no read access and may therefore
				// have missing rows.
				// TODO(ivanpi): If read access is regained, should skipped rows be sent
				// retroactively?
				continue
			}
			return err
		}
		// Send matching rows.
		if err := c.scanInitialState(ctx, call, sender, sntx, watchFilter); err != nil {
			return err
		}
	}
	if err := cxIt.Err(); err != nil {
		return verror.New(verror.ErrInternal, ctx, err)
	}
	return nil
}

// scanInitialState sends the initial state of all matching rows in the
// collection. Does not check access.
// TODO(ivanpi): Abstract out multi-scan for scan and possibly query support.
// TODO(ivanpi): Use watch pattern prefixes to optimize scan ranges.
func (c *collectionReq) scanInitialState(ctx *context.T, call rpc.ServerCall, sender *watchBatchSender, sntx store.SnapshotOrTransaction, watchFilter filter.CollectionRowFilter) error {
	// Scan matching rows.
	rIt := sntx.Scan(common.ScanPrefixArgs(common.JoinKeyParts(common.RowPrefix, c.stKeyPart()), ""))
	defer rIt.Cancel()
	key, value := []byte{}, []byte{}
	for rIt.Advance() {
		key, value = rIt.Key(key), rIt.Value(value)
		// See comment in util/constants.go for why we use SplitNKeyParts.
		parts := common.SplitNKeyParts(string(key), 3)
		externalKey := parts[2]
		// Filter out unnecessary rows.
		if !watchFilter.RowMatches(c.id, externalKey) {
			continue
		}
		// Send row.
		var valueAsRawBytes *vom.RawBytes
		if err := vom.Decode(value, &valueAsRawBytes); err != nil {
			return verror.New(verror.ErrInternal, ctx, err)
		}
		if err := sender.addChange(
			naming.Join(pubutil.EncodeId(c.id), externalKey),
			watch.Exists,
			&wire.StoreChange{
				Value: valueAsRawBytes,
				// Note: FromSync cannot be reconstructed from scan.
				FromSync: false,
			}); err != nil {
			return err
		}
	}
	if err := rIt.Err(); err != nil {
		return verror.New(verror.ErrInternal, ctx, err)
	}
	return nil
}

// watchUpdates waits for database updates and sends them to the client.
// This function does two steps in a for loop:
// - scan through the watch log until the end, sending all updates to the client
// - wait for one of two signals: new updates available or the call is canceled
// The 'new updates' signal is sent by the watcher via a Go channel.
func (d *database) watchUpdates(ctx *context.T, call rpc.ServerCall, sender *watchBatchSender, resumeMarker watch.ResumeMarker, watchFilter filter.CollectionRowFilter) error {
	watcher, cancelWatch := d.st.WatchUpdates(resumeMarker)
	defer cancelWatch()
	for {
		// Drain the log queue.
		for {
			// TODO(ivanpi): Switch to streaming log batch entries? Since sync and
			// conflict resolution merge batches, very large batches may not be
			// unrealistic. However, sync currently also processes an entire batch at
			// a time, and would need to be updated as well.
			logs, nextResumeMarker, err := watcher.NextBatchFromLog(d.st)
			if err != nil {
				// TODO(ivanpi): Log all internal errors, especially ones not returned.
				return verror.NewErrInternal(ctx) // no detailed error before access check
			}
			if logs == nil {
				// No new log records available at this time.
				break
			}
			resumeMarker = nextResumeMarker
			if err := d.processLogBatch(ctx, call, sender, watchFilter, logs); err != nil {
				return err
			}
			if err := sender.finishBatch(resumeMarker); err != nil {
				return err
			}
		}
		// Wait for new updates or cancel.
		select {
		case _, ok := <-watcher.Wait():
			if !ok {
				return watcher.Err()
			}
		case <-ctx.Done():
			return ctx.Err()
		}
	}
}

// processLogBatch converts []*watchable.LogEntry to a watch.Change stream,
// filtering out unnecessary or inaccessible log records.
// Note: Since the governing ACL for each change is no longer tracked, the
// permissions check uses the ACLs in effect at the time processLogBatch is
// called.
// Note: Assumes Read perms on database. Careful if supporting RPCs requiring
// only Resolve.
func (d *database) processLogBatch(ctx *context.T, call rpc.ServerCall, sender *watchBatchSender, watchFilter filter.CollectionRowFilter, logs []*watchable.LogEntry) error {
	allowWatchDbContinue := []access.Tag{access.Read}

	sn := d.st.NewSnapshot()
	defer sn.Abort()
	// Check permissions on Database.
	if _, err := common.GetPermsWithAuth(ctx, call, d, allowWatchDbContinue, sn); err != nil {
		return err
	}
	valueBytes := []byte{}
	for _, logEntry := range logs {
		var opKey string
		var op interface{}
		if err := logEntry.Op.ToValue(&op); err != nil {
			return verror.NewErrInternal(ctx) // no detailed error before access check
		}
		switch op := op.(type) {
		case *watchable.PutOp:
			opKey = string(op.Key)
		case *watchable.DeleteOp:
			opKey = string(op.Key)
		default:
			continue
		}
		// TODO(rogulenko,ivanpi): Currently we only process rows and collection
		// perms. Consider making watchable and processing other keys.
		switch common.FirstKeyPart(opKey) {
		case common.RowPrefix:
			cxId, row, err := common.ParseRowKey(opKey)
			if err != nil {
				return verror.NewErrInternal(ctx) // no detailed error before access check
			}
			// Filter out unnecessary rows.
			if !watchFilter.RowMatches(cxId, row) {
				continue
			}
			// Filter out rows with no read access.
			// TODO(ivanpi): Check only once per collection per batch.
			// TODO(ivanpi): Check service and database resolve only once per batch.
			c := &collectionReq{
				id: cxId,
				d:  d,
			}
			if _, err := common.GetPermsWithAuth(ctx, call, c, []access.Tag{access.Read}, sn); err != nil {
				if verror.ErrorID(err) == verror.ErrNoAccess.ID || verror.ErrorID(err) == verror.ErrNoExist.ID {
					// Skip sending rows if the collection is inaccessible. Caller can see
					// from collection info that they have no read access and may therefore
					// have missing rows.
					// Note, the collection may not exist anymore, in which case permissions
					// cannot be retrieved. This case is treated the same as ErrNoAccess, by
					// skipping the row.
					// TODO(ivanpi): Consider using the implicit ACL instead for nonexistent
					// collections.
					// TODO(ivanpi): If read access is regained, should skipped rows be sent
					// retroactively?
					continue
				}
				return err
			}
			switch op := op.(type) {
			case *watchable.PutOp:
				// Note, valueBytes is reused on each iteration, so the reference must not
				// be used beyond this case block. The code below is safe since only the
				// VOM-decoded copy is used after the call to vom.Decode.
				if valueBytes, err = watchable.GetAtVersion(ctx, sn, op.Key, valueBytes, op.Version); err != nil {
					return verror.New(verror.ErrInternal, ctx, err)
				}
				var rowValueAsRawBytes *vom.RawBytes
				if err := vom.Decode(valueBytes, &rowValueAsRawBytes); err != nil {
					return verror.New(verror.ErrInternal, ctx, err)
				}
				if err := sender.addChange(
					naming.Join(pubutil.EncodeId(cxId), row),
					watch.Exists,
					&wire.StoreChange{
						Value:    rowValueAsRawBytes,
						FromSync: logEntry.FromSync,
					}); err != nil {
					return err
				}
			case *watchable.DeleteOp:
				if err := sender.addChange(
					naming.Join(pubutil.EncodeId(cxId), row),
					watch.DoesNotExist,
					&wire.StoreChange{
						FromSync: logEntry.FromSync,
					}); err != nil {
					return err
				}
			}

		case common.CollectionPermsPrefix:
			// Database permissions for Watch ensure that the user is always allowed
			// to know that a collection exists.
			cxId, err := common.ParseCollectionPermsKey(opKey)
			if err != nil {
				return verror.New(verror.ErrInternal, ctx, err)
			}
			// Filter out unnecessary collections.
			if !watchFilter.CollectionMatches(cxId) {
				continue
			}
			switch op := op.(type) {
			case *watchable.PutOp:
				if valueBytes, err = watchable.GetAtVersion(ctx, sn, op.Key, valueBytes, op.Version); err != nil {
					return verror.NewErrInternal(ctx) // no detailed error for cxPerms before filtering cxInfo
				}
				var cxPerms interfaces.CollectionPerms
				if err := vom.Decode(valueBytes, &cxPerms); err != nil {
					return verror.NewErrInternal(ctx) // no detailed error for cxPerms before filtering cxInfo
				}
				cxInfo := collectionInfoFromPerms(ctx, call, cxPerms.GetPerms())
				cxInfoAsRawBytes, err := vom.RawBytesFromValue(cxInfo)
				if err != nil {
					return verror.New(verror.ErrInternal, ctx, err)
				}
				if err := sender.addChange(
					pubutil.EncodeId(cxId),
					watch.Exists,
					&wire.StoreChange{
						Value:    cxInfoAsRawBytes,
						FromSync: logEntry.FromSync,
					}); err != nil {
					return err
				}
			case *watchable.DeleteOp:
				if err := sender.addChange(
					pubutil.EncodeId(cxId),
					watch.DoesNotExist,
					&wire.StoreChange{
						FromSync: logEntry.FromSync,
					}); err != nil {
					return err
				}
			}

		default:
			continue
		}
	}
	return nil
}

// collectionInfoFromPerms converts a collection permissions object into a
// StoreChangeCollectionInfo tailored to the caller. The returned collection
// info is safe to send to the caller, assuming the caller is allowed to know
// the collection exists. It includes a set listing all access tags that the
// caller has on the collection. The collection permissions object itself is
// included only if the caller is allowed to see it (has Admin permissions).
func collectionInfoFromPerms(ctx *context.T, call rpc.ServerCall, cxPerms access.Permissions) *wire.StoreChangeCollectionInfo {
	ci := &wire.StoreChangeCollectionInfo{
		Allowed: make(map[access.Tag]struct{}),
	}
	for tag, acl := range cxPerms {
		if acl.Authorize(ctx, call.Security()) == nil {
			ci.Allowed[access.Tag(tag)] = struct{}{}
		}
	}
	if _, isAdmin := ci.Allowed[access.Admin]; isAdmin {
		ci.Perms = cxPerms
	}
	return ci
}

// watchBatchSender sends a sequence of watch changes forming a batch, delaying
// sends to allow setting the Continued flag on the last change.
type watchBatchSender struct {
	// Function for sending changes to the stream. Must be set.
	send func(item watch.Change) error

	// Change set by previous addChange, sent by next addChange or finishBatch.
	staged *watch.Change
}

// addChange sends the previously added change (if any) with Continued set to
// true and stages the new one to be sent by the next addChange or finishBatch.
func (w *watchBatchSender) addChange(name string, state int32, storeChange *wire.StoreChange) error {
	// Encode the StoreChange for sending.
	storeChangeAsRawBytes, err := vom.RawBytesFromValue(*storeChange)
	if err != nil {
		return verror.New(verror.ErrInternal, nil, err)
	}
	// Send previously staged change now that we know the batch is continuing.
	if w.staged != nil {
		w.staged.Continued = true
		if err := w.send(*w.staged); err != nil {
			return err
		}
	}
	// Stage new change.
	w.staged = &watch.Change{
		Name:  name,
		State: state,
		Value: storeChangeAsRawBytes,
	}
	return nil
}

// finishBatch sends the previously added change (if any) with Continued set to
// false, finishing the batch.
func (w *watchBatchSender) finishBatch(resumeMarker watch.ResumeMarker) error {
	// Send previously staged change as last in batch.
	if w.staged != nil {
		w.staged.Continued = false
		w.staged.ResumeMarker = resumeMarker
		if err := w.send(*w.staged); err != nil {
			return err
		}
	}
	// Clear staged change.
	w.staged = nil
	return nil
}
