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

// Utilities for testing sync.

import (
	"fmt"
	"os"
	"path"
	"testing"
	"time"

	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/security/access"
	wire "v.io/v23/services/syncbase"
	"v.io/v23/verror"
	"v.io/x/ref/services/syncbase/common"
	"v.io/x/ref/services/syncbase/server/interfaces"
	"v.io/x/ref/services/syncbase/store"
	storeutil "v.io/x/ref/services/syncbase/store/util"
	"v.io/x/ref/services/syncbase/store/watchable"
	"v.io/x/ref/services/syncbase/vclock"
	"v.io/x/ref/test"
)

var (
	mockDbId     = wire.Id{Blessing: "mockapp", Name: "mockdb"}
	mockCRStream *conflictResolverStream
	mockSgPerms  = access.Permissions{}.Add("mockuser", access.TagStrings(wire.AllSyncgroupTags...)...)
)

// mockService emulates a Syncbase service that includes store and sync.
// It is used to access mock databases.
type mockService struct {
	engine   string
	dir      string
	st       store.Store
	vclock   *vclock.VClock
	sync     *syncService
	shutdown func()
}

func (s *mockService) St() store.Store {
	return s.st
}

func (s *mockService) Sync() interfaces.SyncServerMethods {
	return s.sync
}

func (s *mockService) Database(ctx *context.T, call rpc.ServerCall, dbId wire.Id) (interfaces.Database, error) {
	wst, err := watchable.Wrap(s.st, s.vclock, &watchable.Options{
		ManagedPrefixes: []string{common.RowPrefix, common.CollectionPermsPrefix},
	})
	if err != nil {
		return nil, err
	}
	return &mockDatabase{st: wst}, nil
}

func (s *mockService) DatabaseIds(ctx *context.T, call rpc.ServerCall) ([]wire.Id, error) {
	return []wire.Id{mockDbId}, nil
}

func (s *mockService) GetDataWithExistAuth(ctx *context.T, call rpc.ServerCall, st store.StoreReader, v common.PermserData) (parentPerms, perms access.Permissions, existErr error) {
	return nil, nil, verror.NewErrNotImplemented(ctx)
}

func (s *mockService) PermserData() common.PermserData {
	return nil
}

// mockDatabase emulates a Syncbase Database. It is used to test sync
// functionality.
type mockDatabase struct {
	st *watchable.Store
}

func (d *mockDatabase) Id() wire.Id {
	return mockDbId
}

func (d *mockDatabase) Service() interfaces.Service {
	return nil
}

func (d *mockDatabase) St() *watchable.Store {
	return d.st
}

func (d *mockDatabase) CheckExists(ctx *context.T, call rpc.ServerCall) error {
	return nil
}

func (d *mockDatabase) GetCollectionPerms(ctx *context.T, cxId wire.Id, st store.StoreReader) (access.Permissions, error) {
	return nil, verror.NewErrNotImplemented(ctx)
}

func (d *mockDatabase) GetSchemaMetadataInternal(ctx *context.T) (*wire.SchemaMetadata, error) {
	return nil, verror.NewErrNoExist(ctx)
}

func (d *mockDatabase) CrConnectionStream() wire.ConflictManagerStartConflictResolverServerStream {
	return mockCRStream
}

func (d *mockDatabase) ResetCrConnectionStream() {
	mockCRStream = nil
}

func (d *mockDatabase) GetDataWithExistAuth(ctx *context.T, call rpc.ServerCall, st store.StoreReader, v common.PermserData) (parentPerms, perms access.Permissions, existErr error) {
	return nil, nil, verror.NewErrNotImplemented(ctx)
}

func (d *mockDatabase) PermserData() common.PermserData {
	return nil
}

// createService creates a mock Syncbase service used for testing sync
// functionality.
func createService(t *testing.T) *mockService {
	ctx, shutdown := test.V23Init()
	engine := store.EngineForTest
	opts := storeutil.OpenOptions{CreateIfMissing: true, ErrorIfExists: false}
	dir := fmt.Sprintf("%s/vsync_test_%d_%d", os.TempDir(), os.Getpid(), time.Now().UnixNano())

	st, err := storeutil.OpenStore(engine, path.Join(dir, engine), opts)
	if err != nil {
		t.Fatalf("cannot create store %s (%s): %v", engine, dir, err)
	}

	cl := vclock.NewVClock(st)
	if err := cl.InitVClockData(); err != nil {
		t.Fatalf("InitVClockData failed: %v", err)
	}

	s := &mockService{
		engine:   engine,
		dir:      dir,
		st:       st,
		vclock:   cl,
		shutdown: shutdown,
	}
	if s.sync, err = New(ctx, s, engine, dir, cl, true); err != nil {
		storeutil.DestroyStore(engine, dir)
		t.Fatalf("cannot create sync service: %v", err)
	}
	return s
}

// createDatabase creates a mock database.
// TODO(sadovsky): These mocks use methods like s.Database in ways that violate
// the API contract. Can we eliminate them and just use the actual
// implementations?
func createDatabase(t *testing.T, s *mockService) *mockDatabase {
	db, err := s.Database(nil, nil, mockDbId)
	if err != nil {
		t.Errorf("Error while accessing Database: %v", err)
	}
	// TODO(razvanm): Get rid of the type assertion from below.
	return db.(*mockDatabase)
}

func setMockCRStream(crs *conflictResolverStream) {
	mockCRStream = crs
}

// destroyService cleans up the mock Syncbase service.
func destroyService(t *testing.T, s *mockService) {
	defer s.shutdown()
	defer Close(s.sync)
	if err := storeutil.DestroyStore(s.engine, s.dir); err != nil {
		t.Fatalf("cannot destroy store %s (%s): %v", s.engine, s.dir, err)
	}
}

// makeCxId returns a collection id with a default user blessing.
func makeCxId(name string) wire.Id {
	return wire.Id{Blessing: "mockuser", Name: name}
}

// makeRowKey returns the database row key for a given application key.
func makeRowKey(key string) string {
	return common.JoinKeyParts(common.RowPrefix, key)
}

func makeRowKeyFromParts(cxBlessing, cxName, row string) string {
	return common.JoinKeyParts(common.RowPrefix, common.EncodeIdKeyPart(wire.Id{cxBlessing, cxName}), row)
}

func makeCollectionPermsKey(cxBlessing, cxName string) string {
	// TODO(rdaoud,ivanpi): See hack in collection.go.
	return common.JoinKeyParts(common.CollectionPermsPrefix, common.EncodeIdKeyPart(wire.Id{cxBlessing, cxName}), "")
}

// conflictResolverStream mock for testing.
type conflictResolverStream struct {
	sendQ   []wire.ConflictInfo
	recvQ   []wire.ResolutionInfo
	sendErr error
	recvErr error
}

func (crs *conflictResolverStream) RecvStream() interface {
	Advance() bool
	Value() wire.ResolutionInfo
	Err() error
} {
	return &recvStream{index: -1, cr: crs}
}

func (crs *conflictResolverStream) SendStream() interface {
	Send(item wire.ConflictInfo) error
} {
	return &sendStream{cr: crs}
}

type sendStream struct {
	cr *conflictResolverStream
}

func (ss *sendStream) Send(item wire.ConflictInfo) error {
	if ss.cr.sendErr != nil {
		return ss.cr.sendErr
	}
	ss.cr.sendQ = append(ss.cr.sendQ, item)
	return nil
}

type recvStream struct {
	index int
	cr    *conflictResolverStream
}

func (rs *recvStream) Advance() bool {
	rs.index++
	return rs.index < len(rs.cr.recvQ)
}

func (rs *recvStream) Value() wire.ResolutionInfo {
	return rs.cr.recvQ[rs.index]
}

func (rs *recvStream) Err() error {
	return rs.cr.recvErr
}
