// 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.Shutdown(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
}
