package langext

import (
	"fmt"
	"time"
)

func Coalesce[T any](v1 *T, def T) T {
	if v1 != nil {
		return *v1
	}

	return def
}

func CoalesceOpt[T any](v1 *T, v2 *T) *T {
	if v1 != nil {
		return v1
	}

	return v2
}

func Coalesce3[T any](v1 *T, v2 *T, def T) T {
	if v1 != nil {
		return *v1
	}

	if v2 != nil {
		return *v2
	}

	return def
}

func Coalesce3Opt[T any](v1 *T, v2 *T, v3 *T) *T {
	if v1 != nil {
		return v1
	}

	if v2 != nil {
		return v2
	}

	return v3
}

func Coalesce4[T any](v1 *T, v2 *T, v3 *T, def T) T {
	if v1 != nil {
		return *v1
	}

	if v2 != nil {
		return *v2
	}

	if v3 != nil {
		return *v3
	}

	return def
}

func Coalesce4Opt[T any](v1 *T, v2 *T, v3 *T, v4 *T) *T {
	if v1 != nil {
		return v1
	}

	if v2 != nil {
		return v2
	}

	if v3 != nil {
		return v3
	}

	return v4
}

func CoalesceString(s *string, def string) string {
	if s == nil {
		return def
	} else {
		return *s
	}
}

func CoalesceInt(i *int, def int) int {
	if i == nil {
		return def
	} else {
		return *i
	}
}

func CoalesceInt32(i *int32, def int32) int32 {
	if i == nil {
		return def
	} else {
		return *i
	}
}

func CoalesceBool(b *bool, def bool) bool {
	if b == nil {
		return def
	} else {
		return *b
	}
}

func CoalesceTime(t *time.Time, def time.Time) time.Time {
	if t == nil {
		return def
	} else {
		return *t
	}
}

func CoalesceStringer(s fmt.Stringer, def string) string {
	if IsNil(s) {
		return def
	} else {
		return s.String()
	}
}

func SafeCast[T any](v any, def T) T {
	switch r := v.(type) {
	case T:
		return r
	default:
		return def
	}
}