/*
 * Copyright (c) 2021 ETSI STF 625
 *
 * 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 systemTest

import (
	"context"
	"encoding/json"
	"fmt"
	"testing"
	"time"

	log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
	visClient "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-vis-client"
)

var visAppClient *visClient.APIClient
var visServerUrl string

// MEC-030 Clause 6.2.5	Type: PredictedQos, replaced by inteface{} in models

func init() {

	err := startSystemTest()
	if err != nil {
		log.Error("Cannot start system test: ", err)
	}
	//create client
	visAppClientCfg := visClient.NewConfiguration()
	if hostUrlStr == "" {
		hostUrlStr = "http://localhost"
	}

	visAppClientCfg.BasePath = hostUrlStr + "/" + sandboxName + "/vis/v2"

	visAppClient = visClient.NewAPIClient(visAppClientCfg)
	if visAppClient == nil {
		log.Error("Failed to create VIS App REST API client: ", visAppClientCfg.BasePath)
	}
	//NOTE: if localhost is set as the hostUrl, might not be reachable from the service, export MEEP_HOST_TEST_URL ="http://[yourhost]"
	visServerUrl = hostUrlStr + ":" + httpListenerPort
}

func initialiseVisTest() {
	log.Info("activating Scenario")
	err := activateScenario("vis-system-test")
	if err != nil {
		log.Fatal("Scenario cannot be activated: ", err)
	}
	time.Sleep(1000 * time.Millisecond)
	if isAutomationReady(true, 10, 0) {
		geAutomationUpdate(true, false, true, true)
	}
}

func clearUpVisTest() {
	log.Info("terminating Scenario")
	terminateScenario()
	time.Sleep(1000 * time.Millisecond)
}

//no really a test, but loading the scenarios needed that will be used in the following tests
//deletion of those scenarios at the end
func Test_VIS_load_scenarios(t *testing.T) {

	// no override if the name is already in the DB.. security not to override something important
	err := createScenario("vis-system-test", "vis-system-test.yaml")
	if err != nil {
		t.Fatal("Cannot create scenario, keeping the one already there and continuing testing with it :", err)
	}
}

func Test_VIS_periodic_4g_5gNei(t *testing.T) {
	fmt.Println("--- ", t.Name())
	log.MeepTextLogInit(t.Name())

	initialiseVisTest()
	defer clearUpVisTest()

	// Initialize the data structure for the POST request
	// MEC-030 Clause 6.2.5
	// MEC-030 Clause 7.6.3.4
	pointA := visClient.LocationInfoGeoArea{Longitude: 7.413917, Latitude: 43.733505}
	locationInfoA := visClient.LocationInfo{GeoArea: &pointA}
	tsA := visClient.TimeStamp{NanoSeconds: 0, Seconds: 45}
	pointB := visClient.LocationInfoGeoArea{Longitude: 7.413916, Latitude: 43.733515}
	locationInfoB := visClient.LocationInfo{GeoArea: &pointB}
	tsB := visClient.TimeStamp{NanoSeconds: 0, Seconds: 45}
	// Fill PredictedQosRoutesRouteInfo with LocationInfo list
	routeInfo := make([]visClient.PredictedQosRoutesRouteInfo, 2)
	routeInfo[0] = visClient.PredictedQosRoutesRouteInfo{
		Location: &locationInfoA,
		Rsrq:     0,
		Rsrp:     0,
		Time:     &tsA,
	}
	routeInfo[1] = visClient.PredictedQosRoutesRouteInfo{
		Location: &locationInfoB,
		Rsrq:     0,
		Rsrp:     0,
		Time:     &tsB,
	}
	// PredictedQosRoutes with PredictedQosRoutesRouteInfo list
	predictedQosRoutes := visClient.PredictedQosRoutes{RouteInfo: routeInfo}
	// Fill PredictedQos with PredictedQosRoutes list
	routes := make([]visClient.PredictedQosRoutes, 1)
	routes[0] = predictedQosRoutes
	testPredictedQos := visClient.PredictedQos{
		LocationGranularity: "100",
		Routes:              routes,
	}
	fmt.Println("testPredictedQos: ", testPredictedQos)

	// Moving to initial position
	testAddress := "ue2"
	geMoveAssetCoordinates(testAddress, 7.413917, 43.733505)
	time.Sleep(2000 * time.Millisecond)

	// Request to test
	err := visPeriodicSubPOST(testPredictedQos)
	if err != nil {
		t.Fatal("Subscription failed: ", err)
	}

	//only check the first one, the same one is repeated every second
	//hard to say if the period should cover 2 or 3 response... based on the timer timing
	if len(httpReqBody) > 1 {
		var body visClient.PredictedQos
		err = json.Unmarshal([]byte(httpReqBody[0]), &body)
		if err != nil {
			t.Fatalf("cannot unmarshall response")
		}
		errStr := validatePredictedQos(&body, &testPredictedQos)
		if errStr != "" {
			printHttpReqBody()
			t.Fatalf(errStr)
		}

	} else {
		printHttpReqBody()
		t.Fatalf("Number of expected notifications not received")
	}

}

func visPeriodicSubPOST(testPredictedQos visClient.PredictedQos) error {
	//PredictedQosPOST(ctx context.Context, body PredictedQos) (PredictedQos, *http.Response, error)
	_, _, err := visAppClient.V2xiApi.PredictedQosPOST(context.TODO(), testPredictedQos)
	if err != nil {
		log.Error("Failed to send subscription: ", err)
		return err
	}

	return nil
}

func validatePredictedQos(response *visClient.PredictedQos, expectedAssocId *visClient.PredictedQos) string {
	fmt.Println(">>> validatePredictedQos: ", response)
	fmt.Println(">>> validatePredictedQos: ", expectedAssocId)

	if response.LocationGranularity != expectedAssocId.LocationGranularity {
		return ("PredictedQos.LocationGranularity not as expected: " + response.LocationGranularity + " instead of " + expectedAssocId.LocationGranularity)
	}

	return ""
}
