package garif

import (
	"reflect"
	"testing"
)

type (
	nonfatal struct{}
	fatal    struct{}
)

var (
	assert  nonfatal
	require fatal
)

func (nonfatal) Equal(t *testing.T, expected, actual any) {
	t.Helper()
	if !reflect.DeepEqual(expected, actual) {
		t.Errorf("Not equal: expected: %#v, actual: %#v", expected, actual)
	}
}

func (nonfatal) Nil(t *testing.T, value any) {
	t.Helper()
	if !isNil(value) {
		t.Errorf("Expected nil, got: %#v", value)
	}
}

func (nonfatal) True(t *testing.T, value bool) {
	t.Helper()
	if !value {
		t.Errorf("Expected true, got false")
	}
}

func (fatal) NotNil(t *testing.T, value any) {
	t.Helper()
	if isNil(value) {
		t.Fatalf("Expected not nil")
	}
}

func (fatal) Equal(t *testing.T, expected, actual any) {
	t.Helper()
	if !reflect.DeepEqual(expected, actual) {
		t.Fatalf("Not equal: expected: %#v, actual: %#v", expected, actual)
	}
}

func isNil(i any) bool {
	if i == nil {
		return true
	}
	v := reflect.ValueOf(i)
	switch v.Kind() {
	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice:
		return v.IsNil()
	}
	return false
}
