package comfunc

import (
	
	
	
	
	

	
	
)

// Bool try to convert type to bool
func ( any) bool {
	,  := ToBool()
	return 
}

// ToBool try to convert type to bool
func ( any) (bool, error) {
	if ,  := .(bool);  {
		return , nil
	}

	if ,  := .(string);  {
		return StrToBool()
	}
	return false, comdef.ErrConvType
}

// StrToBool parse string to bool. like strconv.ParseBool()
func ( string) (bool, error) {
	 := strings.ToLower()
	switch  {
	case "1", "on", "yes", "true":
		return true, nil
	case "0", "off", "no", "false":
		return false, nil
	}

	return false, fmt.Errorf("'%s' cannot convert to bool", )
}

// FormatWithArgs format message with args
//
//  - only one element, format to string
//  - first is format: fmt.Sprintf(firstElem, fmtAndArgs[1:]...)
//  - all is args: return fmt.Sprint(fmtAndArgs...)
func ( []any) string {
	 := len()
	if  == 0 {
		return ""
	}

	 := [0]
	if  == 1 {
		if ,  := .(string);  {
			return 
		}
		return fmt.Sprintf("%+v", )
	}

	// is template string.
	if ,  := .(string);  && strings.IndexByte(, '%') >= 0 {
		return fmt.Sprintf(, [1:]...)
	}
	return fmt.Sprint(...)
}

// ConvOption convert options
type ConvOption struct {
	// if ture: value is nil, will return convert error;
	// if false(default): value is nil, will convert to zero value
	NilAsFail bool
	// HandlePtr auto convert ptr type(int,float,string) value. eg: *int to int
	// 	- if true: will use real type try convert. default is false
	//	- NOTE: current T type's ptr is default support.
	HandlePtr bool
	// set custom fallback convert func for not supported type.
	UserConvFn comdef.ToStringFunc
}

// ConvOptionFn convert option func
type ConvOptionFn func(opt *ConvOption)

// StrBySprintFn convert any value to string by fmt.Sprint
var StrBySprintFn = func( any) (string, error) {
	return fmt.Sprint(), nil
}

// WithUserConvFn set ConvOption.UserConvFn option
func ( comdef.ToStringFunc) ConvOptionFn {
	return func( *ConvOption) {
		.UserConvFn = 
	}
}

// NewConvOption create a new ConvOption
func ( ...ConvOptionFn) *ConvOption {
	 := &ConvOption{}
	.WithOption(...)
	return 
}

// WithOption set convert option
func ( *ConvOption) ( ...ConvOptionFn) {
	for ,  := range  {
		if  != nil {
			()
		}
	}
}

// ToStringWith try to convert value to string. can with some option func, more see ConvOption.
func ( any,  ...ConvOptionFn) ( string,  error) {
	switch value := .(type) {
	case int:
		 = strconv.Itoa()
	case int8:
		 = strconv.Itoa(int())
	case int16:
		 = strconv.Itoa(int())
	case int32: // same as `rune`
		 = strconv.Itoa(int())
	case int64:
		 = strconv.FormatInt(, 10)
	case uint:
		 = strconv.FormatUint(uint64(), 10)
	case uint8:
		 = strconv.FormatUint(uint64(), 10)
	case uint16:
		 = strconv.FormatUint(uint64(), 10)
	case uint32:
		 = strconv.FormatUint(uint64(), 10)
	case uint64:
		 = strconv.FormatUint(, 10)
	case float32:
		 = strconv.FormatFloat(float64(), 'f', -1, 32)
	case float64:
		 = strconv.FormatFloat(, 'f', -1, 64)
	case bool:
		 = strconv.FormatBool()
	case string:
		 = 
	case *string:
		 = *
	case []byte:
		 = string()
	case time.Duration:
		 = strconv.FormatInt(int64(), 10)
	case fmt.Stringer:
		 = .String()
	case error:
		 = .Error()
	default:
		if len() == 0 &&  == nil {
			return "", nil
		}

		 := NewConvOption(...)
		if  == nil {
			if .NilAsFail {
				 = comdef.ErrConvType
			}
			return
		}

		if .HandlePtr {
			if  := reflect.ValueOf(); .Kind() == reflect.Pointer {
				 = .Elem()
				if checkfn.IsSimpleKind(.Kind()) {
					return (.Interface(), ...)
				}
			}
		}

		if .UserConvFn != nil {
			,  = .UserConvFn()
		} else {
			 = comdef.ErrConvType
		}
	}
	return
}