package testhelper

import (
	"fmt"
	"reflect"
	"testing"
)

func NoError(t *testing.T, name string, err error) bool {
	if err == nil {
		return false
	}

	t.Errorf(TestErrorTemplate, name, nil, err)
	return true
}

func Error(t *testing.T, name string, err error) {
	if err != nil {
		return
	}
	t.Errorf(TestErrorTemplate, name, "Some error", err)
}

func getLen(object interface{}) (ok bool, length int) {
	v := reflect.ValueOf(object)
	defer func() {
		if e := recover(); e != nil {
			ok = false
		}
	}()
	return true, v.Len()
}

func Len(t *testing.T, name string, object interface{}, length int) {
	ok, l := getLen(object)
	if !ok {
		t.Errorf(TestErrorTemplate, name, "could not be applied builtin len", false)
	}

	if l != length {
		t.Errorf(TestErrorTemplate, name, fmt.Sprintf("length of %d", length), l)
	}
}

func Equal(t *testing.T, name string, expected interface{}, actual interface{}) {
	if expected != actual {
		t.Errorf(TestErrorTemplate, name, expected, actual)
	}
}

func EqualByteArray(t *testing.T, name string, expected []byte, actual []byte) {
	if len(expected) != len(actual) {
		t.Errorf(TestErrorTemplate, fmt.Sprintf("%s len", name), len(expected), len(actual))
	} else {
		for i, b := range actual {
			Equal(t, fmt.Sprintf("%s byte %d", name, i), expected[i], b)
		}
	}
}

func Same(t *testing.T, name string, expected interface{}, actual interface{}) {
	if !reflect.DeepEqual(expected, actual) {
		t.Errorf(TestErrorTemplate, name, expected, actual)
	}
}

func True(t *testing.T, name string, actual bool) {
	Equal(t, name, true, actual)
}

func MapKeyExists(t *testing.T, name string, m map[string]interface{}, key string) {
	if _, ok := m[key]; !ok {
		t.Errorf(TestErrorTemplate, name, nil, key)
	}
}

func MapKeyNotExists(t *testing.T, name string, m map[string]interface{}, key string) {
	if _, ok := m[key]; ok {
		t.Errorf(TestErrorTemplate, name, key, nil)
	}
}

func MapHasValue(t *testing.T, name string, m map[string]interface{}, key string, value interface{}) {
	if val, ok := m[key]; ok {
		if value != val {
			t.Errorf(TestErrorTemplate, fmt.Sprintf("%s %s", name, key), value, val)
		}
	} else {
		t.Errorf(TestErrorTemplate, fmt.Sprintf("%s missing %s", name, key), key, nil)
	}
}
