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

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

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/x/ref/test/v23test"
	"v.io/x/sensorlog/internal/client"
	sltu "v.io/x/sensorlog/internal/client/testutil"
	"v.io/x/sensorlog/internal/sbmodel"
	"v.io/x/sensorlog/internal/sbutil"
)

func TestV23StreamConfigAndList(t *testing.T) {
	v23test.SkipUnlessRunningIntegrationTests(t)
	sh := v23test.NewShell(t, v23test.Opts{})
	defer sh.Cleanup()
	sh.StartRootMountTable()
	mtName := v23.GetNamespace(sh.Ctx).Roots()[0]

	clientSb := "sb/client"
	clientCtx := sh.ForkContext("u:client")
	clientSbCreds := sh.ForkCredentials("u:client:sb")
	sh.StartSyncbase(clientSbCreds, clientSb, "",
		`{"Read": {"In":["root:u:client"]}, "Write": {"In":["root:u:client"]}, "Admin": {"In":["root:u:client"]}, "Resolve": {"In":["..."]}}`)

	measuredSb := "sb/measured"
	measuredCreds := sh.ForkCredentials("u:measured")
	measuredSbCreds := sh.ForkCredentials("u:measured:sb")
	sh.StartSyncbase(measuredSbCreds, measuredSb, "",
		`{"Read": {"In":["root:u:measured"]}, "Write": {"In":["root:u:measured"]}, "Admin": {"In":["root:u:measured"]}, "Resolve": {"In":["..."]}}`)

	time.Sleep(1 * time.Second)

	// Start measured.
	measuredPath := sh.BuildGoPkg("v.io/x/sensorlog/measured")
	devId := "measured1"
	publishSb := naming.Join(mtName, measuredSb)
	measured := sh.Cmd(measuredPath, "-alsologtostderr", "-service="+measuredSb,
		"-devid="+devId, "-admin=root:u:client", "-publish-sb="+publishSb)
	measured = measured.WithCredentials(measuredCreds)
	measured.PropagateOutput = true
	measured.Start()

	time.Sleep(3 * time.Second)

	// Add measuring device to client, joining its syncgroup.
	if err := sltu.AddTestDevice(clientCtx, clientSb, devId, publishSb); err != nil {
		t.Errorf("failed adding device %s: %v", devId, err)
	}

	// Create streams.
	streamId1, result1, interval1 := "str1", 42.0, 2*time.Second
	if err := sltu.CreateTestStream(clientCtx, clientSb, devId,
		streamId1, fmt.Sprintf("echo %f;", result1), interval1); err != nil {
		t.Errorf("failed creating stream %s: %v", streamId1, err)
	}

	time.Sleep(1 * time.Second)

	streamId2, result2, interval2 := "str2", 47.0, 1*time.Second
	if err := sltu.CreateTestStream(clientCtx, clientSb, devId,
		streamId2, fmt.Sprintf("echo %f;", result2), interval2); err != nil {
		t.Errorf("failed creating stream %s: %v", streamId2, err)
	}

	// streamId has another streamId as prefix to verify ListDataStreams prefix
	// handling.
	streamId3, result3, interval3 := "str12", 3.14159, 500*time.Millisecond
	if err := sltu.CreateTestStream(clientCtx, clientSb, devId,
		streamId3, fmt.Sprintf("echo %f;", result3), interval3); err != nil {
		t.Errorf("failed creating stream %s: %v", streamId3, err)
	}

	// Allow time for sync and at least 3 measurements.
	time.Sleep(10 * time.Second)

	// SIGINT will gracefully stop measured.
	measured.Terminate(os.Interrupt)

	// Check that both streams have at least 3 measurements synced back to
	// client device Syncbase.
	if err := listStreamData(clientCtx, clientSb, devId, streamId1, result1); err != nil {
		t.Errorf("failed listing stream %s data: %v", streamId1, err)
	}
	if err := listStreamData(clientCtx, clientSb, devId, streamId2, result2); err != nil {
		t.Errorf("failed listing stream %s data: %v", streamId2, err)
	}
	if err := listStreamData(clientCtx, clientSb, devId, streamId3, result3); err != nil {
		t.Errorf("failed listing stream %s data: %v", streamId3, err)
	}
}

func listStreamData(ctx *context.T, sbService, devId, streamId string, expectVal float64) error {
	db, err := sbutil.CreateOrOpenDB(ctx, sbService, sbmodel.MasterTables)
	if err != nil {
		return fmt.Errorf("failed opening master database: %v", err)
	}

	count := 0
	streamKey := &sbmodel.KStreamDef{
		DevId:    devId,
		StreamId: streamId,
	}
	if err := client.ListStreamData(ctx, db, streamKey, func(key *sbmodel.KDataPoint, val sbmodel.VDataPoint) error {
		if got, want := key.StreamId, streamId; got != want {
			return fmt.Errorf("list returned data for wrong stream: got %s, want %s", got, want)
		}
		switch val := val.(type) {
		case sbmodel.VDataPointValue:
			if val.Value != expectVal {
				return fmt.Errorf("unexpected stream data value, got: %v, want: %v", val.Value, expectVal)
			}
		default:
			return fmt.Errorf("unexpected stream data type, got: %v, want value: %v", val, expectVal)
		}
		count++
		return nil
	}); err != nil {
		return err
	}

	if count < 3 {
		return fmt.Errorf("expected at least 3 measurements for %s, got %d", streamId, count)
	}

	return nil
}
