package utils

import (
	
	
	
	
	
	
	
	
)

var gormSourceDir string

func init() {
	, , ,  := runtime.Caller(0)
	// compatible solution to get gorm source directory with various operating systems
	gormSourceDir = sourceDir()
}

func sourceDir( string) string {
	 := filepath.Dir()
	 = filepath.Dir()

	 := filepath.Dir()
	if filepath.Base() != "gorm.io" {
		 = 
	}
	return filepath.ToSlash() + "/"
}

// FileWithLineNum return the file name and line number of the current file
func () string {
	// the second caller usually from gorm internal, so set i start from 2
	for  := 2;  < 15; ++ {
		, , ,  := runtime.Caller()
		if  && (!strings.HasPrefix(, gormSourceDir) || strings.HasSuffix(, "_test.go")) {
			return  + ":" + strconv.FormatInt(int64(), 10)
		}
	}

	return ""
}

func ( rune) bool {
	return !unicode.IsLetter() && !unicode.IsNumber() &&  != '.' &&  != '*' &&  != '_' &&  != '$' &&  != '@'
}

// CheckTruth check string true or not
func ( ...string) bool {
	for ,  := range  {
		if  != "" && !strings.EqualFold(, "false") {
			return true
		}
	}
	return false
}

func ( ...interface{}) string {
	 := make([]string, len())

	for ,  := range  {
		if ,  := .(driver.Valuer);  {
			, _ = .Value()
		}

		switch v := .(type) {
		case string:
			[] = 
		case []byte:
			[] = string()
		case uint:
			[] = strconv.FormatUint(uint64(), 10)
		default:
			[] = fmt.Sprint(reflect.Indirect(reflect.ValueOf()).Interface())
		}
	}

	return strings.Join(, "_")
}

func ( []string,  string) bool {
	for ,  := range  {
		if  ==  {
			return true
		}
	}
	return false
}

func (,  interface{}) bool {
	if reflect.DeepEqual(, ) {
		return true
	}
	if  == nil ||  == nil {
		return false
	}

	 := reflect.ValueOf()
	 := reflect.ValueOf()
	if .Kind() == reflect.Ptr && .IsNil() ||
		.Kind() == reflect.Ptr && .IsNil() {
		return false
	}

	if ,  := .(driver.Valuer);  {
		, _ = .Value()
	}
	if ,  := .(driver.Valuer);  {
		, _ = .Value()
	}
	return reflect.DeepEqual(, )
}

func ( interface{}) string {
	switch v := .(type) {
	case string:
		return 
	case int:
		return strconv.FormatInt(int64(), 10)
	case int8:
		return strconv.FormatInt(int64(), 10)
	case int16:
		return strconv.FormatInt(int64(), 10)
	case int32:
		return strconv.FormatInt(int64(), 10)
	case int64:
		return strconv.FormatInt(, 10)
	case uint:
		return strconv.FormatUint(uint64(), 10)
	case uint8:
		return strconv.FormatUint(uint64(), 10)
	case uint16:
		return strconv.FormatUint(uint64(), 10)
	case uint32:
		return strconv.FormatUint(uint64(), 10)
	case uint64:
		return strconv.FormatUint(, 10)
	}
	return ""
}

const nestedRelationSplit = "__"

// NestedRelationName nested relationships like `Manager__Company`
func (,  string) string {
	return  + nestedRelationSplit + 
}

// SplitNestedRelationName Split nested relationships to `[]string{"Manager","Company"}`
func ( string) []string {
	return strings.Split(, nestedRelationSplit)
}

// JoinNestedRelationNames nested relationships like `Manager__Company`
func ( []string) string {
	return strings.Join(, nestedRelationSplit)
}