package struct_utils_test

import (
	"fmt"
	"testing"

	"gitlab.com/uafrica/go-utils/struct_utils"
)

func TestParams(t *testing.T) {
	type s struct {
		NameWithoutTag  string //will not be encoded into params!
		NameWithDashTag string `json:"-"`               //will not be encoded into params!
		Name            string `json:"name"`            //encoded always
		NameOmitempty   string `json:"name2,omitempty"` //encoded when not empty
	}
	ps := s{"a", "b", "c", "d"}
	pm := struct_utils.MapParams(ps)
	if len(pm) != 2 || pm["name"] != "c" || pm["name2"] != "d" { //name2 is encoded when not empty
		t.Fatalf("wrong params: %+v != %+v", ps, pm)
	}
	t.Logf("ps=%+v -> pm=%+v", ps, pm)

	ps = s{}
	pm = struct_utils.MapParams(ps)
	if len(pm) != 1 || pm["name"] != "" { //name is always encoded because it has json tag and does not specify omitempty
		t.Fatalf("wrong params: %+v != %+v", ps, pm)
	}
	t.Logf("ps=%+v -> pm=%+v", ps, pm)
}

func TestAnonymous(t *testing.T) {
	type page struct {
		Limit  int64 `json:"limit,omitempty"`
		Offset int64 `json:"offset,omitempty"`
	}
	type get struct {
		ID int64 `json:"id,omitempty"`
		page
	}

	ps := get{ID: 123}
	pm := struct_utils.MapParams(ps)
	if len(pm) != 1 || pm["id"] != "123" {
		t.Fatalf("wrong params: %+v != %+v", ps, pm)
	}
	t.Logf("ps=%+v -> pm=%+v", ps, pm)

	ps = get{page: page{Limit: 444, Offset: 555}}
	pm = struct_utils.MapParams(ps)
	if len(pm) != 2 || pm["limit"] != "444" || pm["offset"] != "555" {
		t.Fatalf("wrong params: %+v != %+v", ps, pm)
	}
	t.Logf("ps=%+v -> pm=%+v", ps, pm)

	ps = get{page: page{Limit: 444, Offset: 555}, ID: 111}
	pm = struct_utils.MapParams(ps)
	if len(pm) != 3 || pm["limit"] != "444" || pm["offset"] != "555" || pm["id"] != "111" {
		t.Fatalf("wrong params: %+v != %+v", ps, pm)
	}
	t.Logf("ps=%+v -> pm=%+v", ps, pm)
}

func TestMapParams(t *testing.T) {
	ps := paramsStruct{ID: 123}
	pm := struct_utils.MapParams(ps)
	if len(pm) != 1 || pm["id"] != "123" {
		t.Fatalf("wrong params: %+v != %+v", ps, pm)
	}
	t.Logf("ps=%+v -> pm=%+v", ps, pm)

	ps = paramsStruct{IDs: []int64{1, 2, 3}}
	pm = struct_utils.MapParams(ps)
	if len(pm) != 1 || pm["ids"] != "[1,2,3]" {
		t.Fatalf("wrong params: %+v != %+v", ps, pm)
	}
	t.Logf("ps=%+v -> pm=%+v", ps, pm)

	ps = paramsStruct{X1: xtype{1}, X3: &xtype{3}}
	pm = struct_utils.MapParams(ps)
	if len(pm) != 2 || pm["x1"] != ">>1<<" || pm["x3"] != ">>3<<" {
		t.Fatalf("wrong params: %+v != %+v", ps, pm)
	}
	t.Logf("ps=%+v -> pm=%+v", ps, pm)
}

type paramsStruct struct {
	ID  int64   `json:"id,omitempty"`
	IDs []int64 `json:"ids,omitempty"`
	X1  xtype   `json:"x1,omitempty"`
	X2  xtype   `json:"x2,omitempty"`
	X3  *xtype  `json:"x3,omitempty"`
	X4  *xtype  `json:"x4,omitempty"`
}

type xtype struct {
	xvalue int
}

func (x xtype) String() string {
	if x.xvalue == 0 {
		return ""
	}
	return fmt.Sprintf(">>%d<<", x.xvalue)
}