package path

import (
	"os"
	"reflect"
	"sort"
	"testing"

	model "code.fbi.h-da.de/danet/gosdn/controller/test/yang"
	"github.com/openconfig/goyang/pkg/yang"
	"github.com/openconfig/ygot/ytypes"
	log "github.com/sirupsen/logrus"
)

var schema *ytypes.Schema

func TestMain(m *testing.M) {
	testSetupPath()
	os.Exit(m.Run())
}

func testSetupPath() {
	var err error
	schema, err = model.Schema()
	if err != nil {
		log.Fatal(err)
	}
}

func TestParseSchema(t *testing.T) {
	t.Skip("order of slices cannot be determined")
	type args struct {
		schema *ytypes.Schema
		root   string
	}
	tests := []struct {
		name    string
		args    args
		want    map[string]*Element
		wantErr bool
	}{
		{
			name: "default",
			args: args{
				schema: schema,
				root:   "device",
			},
			want: map[string]*Element{
				"Test_Container1": {
					Children: []*Element{
						{
							Children: []*Element{
								{
									Children: nil,
									Name:     "leaf-list1",
								},
								{
									Children: nil,
									Name:     "leaf1",
								},
								{
									Children: nil,
									Name:     "leaf2",
								},
							},
							Name: "list1",
						},
					},
					Name: "container1",
				},
				"Test_Container2": {
					Children: []*Element{
						{
							Children: []*Element{
								{
									Children: nil,
									Name:     "leaf-list1",
								},
								{
									Children: nil,
									Name:     "leaf1",
								},
								{
									Children: nil,
									Name:     "leaf2",
								},
							},
							Name: "list1",
						},
					},
					Name: "container2",
				},
			},
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := ParseSchema(tt.args.schema, tt.args.root)
			if (err != nil) != tt.wantErr {
				t.Errorf("ParseSchema() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			sort.Slice(tt.want["Test_Container1"].Children[0].Children[0].Children, func(i, j int) bool {
				return i < j
			})

			sort.Slice(tt.want["Test_Container2"].Children[0].Children[0].Children, func(i, j int) bool {
				return i < j
			})

			sort.Slice(got["Test_Container1"].Children[0].Children[0].Children, func(i, j int) bool {
				return i < j
			})

			sort.Slice(got["Test_Container2"].Children[0].Children[0].Children, func(i, j int) bool {
				return i < j
			})
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("ParseSchema() got = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestStrings(t *testing.T) {
	t.Skip("order of slices cannot be determined")
	type args struct {
		paths map[string]*Element
	}
	tests := []struct {
		name string
		args args
		want []string
	}{
		{
			name: "default",
			args: args{
				paths: map[string]*Element{
					"Test_Container1": {
						Children: []*Element{
							{
								Children: []*Element{
									{
										Children: nil,
										Name:     "leaf-list1",
									},
									{
										Children: nil,
										Name:     "leaf1",
									},
									{
										Children: nil,
										Name:     "leaf2",
									},
								},
								Name: "list1",
							},
						},
						Name: "container1",
					},
					"Test_Container2": {
						Children: []*Element{
							{
								Children: []*Element{
									{
										Children: nil,
										Name:     "leaf-list1",
									},
									{
										Children: nil,
										Name:     "leaf1",
									},
									{
										Children: nil,
										Name:     "leaf2",
									},
								},
								Name: "list1",
							},
						},
						Name: "container2",
					},
				},
			},
			want: []string{
				"/container1/list1/leaf-list1",
				"/container1/list1/leaf1",
				"/container1/list1/leaf2",
				"/container2/list1/leaf-list1",
				"/container2/list1/leaf1",
				"/container2/list1/leaf2",
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := Strings(tt.args.paths)
			sort.Slice(tt.want, func(i, j int) bool {
				return i < j
			})
			sort.Slice(got, func(i, j int) bool {
				return i < j
			})
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("Strings() = %v, want %v", got, tt.want)
			}
		})
	}
}

func Test_processEntry(t *testing.T) {
	t.Skip("order of slices cannot be determined")
	type args struct {
		e *yang.Entry
	}
	tests := []struct {
		name string
		args args
		want *Element
	}{
		{
			name: "leaf",
			args: args{e: schema.SchemaTree["Test_Container1_List1"].Dir["leaf1"]},
			want: &Element{
				Children: nil,
				Name:     "leaf1",
			},
		},
		{
			name: "intermediate",
			args: args{schema.SchemaTree["Test_Container1"]},
			want: &Element{
				Children: []*Element{
					{
						Children: []*Element{
							{
								Children: nil,
								Name:     "leaf-list1",
							},
							{
								Children: nil,
								Name:     "leaf1",
							},
							{
								Children: nil,
								Name:     "leaf2",
							},
						},
						Name: "list1",
					},
				},
				Name: "container1",
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := processEntry(tt.args.e)
			sort.Slice(tt.want.Children, func(i, j int) bool {
				return i < j
			})
			sort.Slice(got.Children, func(i, j int) bool {
				return i < j
			})
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("processEntry() = %v, want %v", got, tt.want)
			}
		})
	}
}
