// +build integration

/*
 * Copyright 2018-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package core

import (
	"context"
	"fmt"
	"github.com/google/uuid"
	"github.com/opencord/voltha-go/common/log"
	tu "github.com/opencord/voltha-go/tests/utils"
	"github.com/opencord/voltha-protos/go/common"
	"github.com/opencord/voltha-protos/go/voltha"
	"github.com/stretchr/testify/assert"
	"google.golang.org/grpc/metadata"
	"math"
	"os"
	"testing"
	"time"
)

var stub voltha.VolthaServiceClient
var volthaSerialNumberKey string

/*
 This local "integration" test uses one RW-Core, one simulated_olt and one simulated_onu adapter to test performance
metrics, in a development environment. It uses docker-compose to set up the local environment. However, it can
easily be extended to run in k8s environment.

The compose files used are located under %GOPATH/src/github.com/opencord/voltha-go/compose. If the GOPATH is not set
then you can specify the location of the compose files by using COMPOSE_PATH to set the compose files location.

To run this test: DOCKER_HOST_IP=<local IP> go test -v

*/

var allDevices map[string]*voltha.Device
var allLogicalDevices map[string]*voltha.LogicalDevice

var composePath string

const (
	GRPC_PORT        = 50057
	NUM_OLTS         = 1
	NUM_ONUS_PER_OLT = 4 // This should coincide with the number of onus per olt in adapters-simulated.yml file
)

var parentPmNames = []string{
	"tx_64_pkts",
	"tx_65_127_pkts",
	"tx_128_255_pkts",
	"tx_256_511_pkts",
	"tx_512_1023_pkts",
	"tx_1024_1518_pkts",
	"tx_1519_9k_pkts",
	"rx_64_pkts",
	"rx_65_127_pkts",
	"rx_128_255_pkts",
	"rx_256_511_pkts",
	"rx_512_1023_pkts",
	"rx_1024_1518_pkts",
	"rx_1519_9k_pkts",
}

var childPmNames = []string{
	"tx_64_pkts",
	"tx_65_127_pkts",
	"tx_128_255_pkts",
	"tx_1024_1518_pkts",
	"tx_1519_9k_pkts",
	"rx_64_pkts",
	"rx_64_pkts",
	"rx_65_127_pkts",
	"rx_128_255_pkts",
	"rx_1024_1518_pkts",
	"rx_1519_9k_pkts",
}

func setup() {
	var err error

	if _, err = log.AddPackage(log.JSON, log.WarnLevel, log.Fields{"instanceId": "testing"}); err != nil {
		log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
	}
	log.UpdateAllLoggers(log.Fields{"instanceId": "testing"})
	log.SetAllLogLevel(log.ErrorLevel)

	volthaSerialNumberKey = "voltha_serial_number"
	allDevices = make(map[string]*voltha.Device)
	allLogicalDevices = make(map[string]*voltha.LogicalDevice)

	grpcHostIP := os.Getenv("DOCKER_HOST_IP")
	goPath := os.Getenv("GOPATH")
	if goPath != "" {
		composePath = fmt.Sprintf("%s/src/github.com/opencord/voltha-go/compose", goPath)
	} else {
		composePath = os.Getenv("COMPOSE_PATH")
	}

	fmt.Println("Using compose path:", composePath)

	//Start the simulated environment
	if err = tu.StartSimulatedEnv(composePath); err != nil {
		fmt.Println("Failure starting simulated environment:", err)
		os.Exit(10)
	}

	stub, err = tu.SetupGrpcConnectionToCore(grpcHostIP, GRPC_PORT)
	if err != nil {
		fmt.Println("Failure connecting to Voltha Core:", err)
		os.Exit(11)
	}

	// Wait for the simulated devices to be registered in the Voltha Core
	adapters := []string{"simulated_olt", "simulated_onu"}
	if _, err = tu.WaitForAdapterRegistration(stub, adapters, 40); err != nil {
		fmt.Println("Failure retrieving adapters:", err)
		os.Exit(12)
	}
}

func shutdown() {
	err := tu.StopSimulatedEnv(composePath)
	if err != nil {
		fmt.Println("Failure stop simulated environment:", err)
	}
}

func refreshLocalDeviceCache(stub voltha.VolthaServiceClient) error {
	retrievedDevices, err := tu.ListDevices(stub)
	if err != nil {
		return err
	}
	for _, d := range retrievedDevices.Items {
		allDevices[d.Id] = d
	}

	retrievedLogicalDevices, err := tu.ListLogicalDevices(stub)
	if err != nil {
		return err
	}

	for _, ld := range retrievedLogicalDevices.Items {
		allLogicalDevices[ld.Id] = ld
	}
	return nil
}

func isPresent(pmName string, pmNames []string) bool {
	for _, name := range pmNames {
		if name == pmName {
			return true
		}
	}
	return false
}

func verifyDevicePMs(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device, allPmNames []string, disabledPmNames []string, frequency uint32) {
	ui := uuid.New()
	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
	pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
	assert.Nil(t, err)
	assert.Equal(t, device.Id, pmConfigs.Id)
	assert.Equal(t, uint32(frequency), pmConfigs.DefaultFreq)
	assert.Equal(t, false, pmConfigs.FreqOverride)
	assert.Equal(t, false, pmConfigs.Grouped)
	assert.Nil(t, pmConfigs.Groups)
	assert.True(t, len(pmConfigs.Metrics) > 0)
	metrics := pmConfigs.Metrics
	for _, m := range metrics {
		if m.Enabled {
			assert.True(t, isPresent(m.Name, allPmNames))
		} else {
			assert.True(t, isPresent(m.Name, disabledPmNames))
		}
		assert.Equal(t, voltha.PmConfig_COUNTER, m.Type)
	}
}

func verifyInitialPmConfigs(t *testing.T, stub voltha.VolthaServiceClient) {
	fmt.Println("Verifying initial PM configs")
	err := refreshLocalDeviceCache(stub)
	assert.Nil(t, err)
	for _, d := range allDevices {
		if d.Root {
			verifyDevicePMs(t, stub, d, parentPmNames, []string{}, 150)
		} else {
			verifyDevicePMs(t, stub, d, childPmNames, []string{}, 150)
		}
	}
}

func verifyPmFrequencyUpdate(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
	ui := uuid.New()
	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
	pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
	assert.Nil(t, err)
	pmConfigs.DefaultFreq = 10
	_, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
	assert.Nil(t, err)
	if device.Root {
		verifyDevicePMs(t, stub, device, parentPmNames, []string{}, 10)
	} else {
		verifyDevicePMs(t, stub, device, childPmNames, []string{}, 10)
	}
}

func updatePmFrequencies(t *testing.T, stub voltha.VolthaServiceClient) {
	fmt.Println("Verifying update to PMs frequencies")
	err := refreshLocalDeviceCache(stub)
	assert.Nil(t, err)
	for _, d := range allDevices {
		verifyPmFrequencyUpdate(t, stub, d)
	}
}

func verifyDisablingSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
	ui := uuid.New()
	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
	pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
	assert.Nil(t, err)
	metricsToDisable := []string{"tx_64_pkts", "rx_64_pkts", "tx_65_127_pkts", "rx_65_127_pkts"}
	for _, m := range pmConfigs.Metrics {
		if isPresent(m.Name, metricsToDisable) {
			m.Enabled = false
		}
	}
	_, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
	assert.Nil(t, err)
	if device.Root {
		verifyDevicePMs(t, stub, device, parentPmNames, metricsToDisable, 10)
	} else {
		verifyDevicePMs(t, stub, device, childPmNames, metricsToDisable, 10)
	}
}

func disableSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient) {
	fmt.Println("Verifying disabling of some PMs")
	err := refreshLocalDeviceCache(stub)
	assert.Nil(t, err)
	for _, d := range allDevices {
		verifyDisablingSomePmMetrics(t, stub, d)
	}
}

func createAndEnableDevices(t *testing.T) {
	err := tu.SetAllLogLevel(stub, voltha.Logging{Level: common.LogLevel_WARNING})
	assert.Nil(t, err)

	err = tu.SetLogLevel(stub, voltha.Logging{Level: common.LogLevel_DEBUG, PackageName: "github.com/opencord/voltha-go/rw_core/core"})
	assert.Nil(t, err)

	startTime := time.Now()

	//Pre-provision the parent device
	oltDevice, err := tu.PreProvisionDevice(stub)
	assert.Nil(t, err)

	fmt.Println("Creation of ", NUM_OLTS, " OLT devices took:", time.Since(startTime))

	startTime = time.Now()

	//Enable all parent device - this will enable the child devices as well as validate the child devices
	err = tu.EnableDevice(stub, oltDevice, NUM_ONUS_PER_OLT)
	assert.Nil(t, err)

	fmt.Println("Enabling of  OLT device took:", time.Since(startTime))

	// Wait until the core and adapters sync up after an enabled
	time.Sleep(time.Duration(math.Max(10, float64(NUM_OLTS*NUM_ONUS_PER_OLT)/2)) * time.Second)

	err = tu.VerifyDevices(stub, NUM_ONUS_PER_OLT)
	assert.Nil(t, err)

	lds, err := tu.VerifyLogicalDevices(stub, oltDevice, NUM_ONUS_PER_OLT)
	assert.Nil(t, err)
	assert.Equal(t, 1, len(lds.Items))
}

func TestPerformanceMetrics(t *testing.T) {
	//1. Test creation and activation of the devices.  This will validate the devices as well as the logical device created/
	createAndEnableDevices(t)

	//	2. Test initial PMs on each device
	verifyInitialPmConfigs(t, stub)

	//	3. Test frequency update of the pmConfigs
	updatePmFrequencies(t, stub)

	//	4. Test disable some PM metrics
	disableSomePmMetrics(t, stub)
}

func TestMain(m *testing.M) {
	setup()
	code := m.Run()
	shutdown()
	os.Exit(code)
}
