package nucleus

import (
	"testing"

	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkdomain"
	"code.fbi.h-da.de/danet/gosdn/controller/store"
	"github.com/google/uuid"
)

func TestAddPnd(t *testing.T) {
	defer ensureStoreFileForTestsIsRemoved(store.PndFilename)

	pluginServiceMock := NewPluginServiceMock()
	pndStore := NewPndStore(pluginServiceMock)

	pndID, _ := uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bad")
	pnd := NewPND(pndID, "testpnd", "test")

	err := pndStore.Add(pnd)

	if err != nil {
		t.Error(err)
	}
}

func TestGetAllPnds(t *testing.T) {
	defer ensureStoreFileForTestsIsRemoved(store.PndFilename)

	pluginServiceMock := NewPluginServiceMock()
	pndStore := NewPndStore(pluginServiceMock)
	pndID1, _ := uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bad")
	pndID2, _ := uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bab")
	pnd1 := NewPND(pndID1, "testpnd", "test")
	pnd2 := NewPND(pndID2, "testpnd2", "test")

	inputPnds := [2]networkdomain.NetworkDomain{pnd1, pnd2}

	for _, pnd := range inputPnds {
		err := pndStore.Add(pnd)
		if err != nil {
			t.Error(err)
		}
	}

	returnPnds, err := pndStore.GetAll()
	if err != nil {
		t.Error(err)
	}

	for i, pnd := range returnPnds {
		if pnd.Name != inputPnds[i].GetName() {
			t.Errorf("GetAll() = %v, want %v", pnd.Name, inputPnds[i].GetName())
		}
		if pnd.Description != inputPnds[i].GetDescription() {
			t.Errorf("GetAll() = %v, want %v", pnd.Description, inputPnds[i].GetDescription())
		}
		if pnd.ID != inputPnds[i].ID().String() {
			t.Errorf("GetAll() = %v, want %v", pnd.ID, inputPnds[i].ID())
		}
	}
}

func TestGetPnd(t *testing.T) {
	defer ensureStoreFileForTestsIsRemoved(store.PndFilename)

	pluginServiceMock := NewPluginServiceMock()
	pndStore := NewPndStore(pluginServiceMock)
	pndID1, _ := uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bad")
	pndID2, _ := uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bab")
	pnd1 := NewPND(pndID1, "testpnd", "test")
	pnd2 := NewPND(pndID2, "testpnd2", "test")

	inputPnds := [2]networkdomain.NetworkDomain{pnd1, pnd2}

	for _, pnd := range inputPnds {
		err := pndStore.Add(pnd)
		if err != nil {
			t.Error(err)
		}
	}

	returnPnd, err := pndStore.Get(store.Query{ID: pndID2, Name: ""})
	if err != nil {
		t.Error(err)
	}

	if returnPnd.Name != pnd2.GetName() {
		t.Errorf("GetAll() = %v, want %v", pnd2.GetName(), returnPnd.Name)
	}
	if returnPnd.Description != pnd2.GetDescription() {
		t.Errorf("GetAll() = %v, want %v", pnd2.GetDescription(), returnPnd.Description)
	}
	if returnPnd.ID != pnd2.ID().String() {
		t.Errorf("GetAll() = %v, want %v", pnd2.ID(), returnPnd.ID)
	}
}

func TestDeletePnd(t *testing.T) {
	defer ensureStoreFileForTestsIsRemoved(store.PndFilename)

	pluginServiceMock := NewPluginServiceMock()
	pndStore := NewPndStore(pluginServiceMock)
	pndID1, _ := uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bad")
	pndID2, _ := uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bab")
	pnd1 := NewPND(pndID1, "testpnd", "test")
	pnd2 := NewPND(pndID2, "testpnd2", "test")

	inputPnds := [2]networkdomain.NetworkDomain{pnd1, pnd2}

	for _, pnd := range inputPnds {
		err := pndStore.Add(pnd)
		if err != nil {
			t.Error(err)
		}
	}

	err := pndStore.Delete(pnd1)
	if err != nil {
		t.Error(err)
	}

	returnPnds, err := pndStore.GetAll()
	if err != nil {
		t.Error(err)
	}

	length := len(returnPnds)
	if length != 1 {
		t.Errorf("GetAll() length of array = %v, want %v", length, 1)
	}

	//only check first element in this case
	for i, pnd := range returnPnds[1:] {
		if pnd.Name != inputPnds[i].GetName() {
			t.Errorf("GetAll() = %v, want %v", pnd.Name, inputPnds[i].GetName())
		}
		if pnd.Description != inputPnds[i].GetDescription() {
			t.Errorf("GetAll() = %v, want %v", pnd.Description, inputPnds[i].GetDescription())
		}
		if pnd.ID != inputPnds[i].ID().String() {
			t.Errorf("GetAll() = %v, want %v", pnd.ID, inputPnds[i].ID())
		}
	}
}
