package safe

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"time"
)

func Uint(s interface{}) uint64 {
	switch tv := s.(type) {
	case nil:
		return 0
	case int:
		return uint64(tv)
	case int64:
		return uint64(tv)
	case uint:
		return uint64(tv)
	case uint64:
		return tv
	case string:
		if i, err := strconv.ParseUint(tv, 10, 64); err != nil {
			log.Panic(err)
		} else {
			return i
		}
	case []byte:
		if i, err := strconv.ParseUint(string(tv), 10, 64); err != nil {
			log.Panic(err)
		} else {
			return i
		}
	default:
		log.Panic(fmt.Sprintf("not impl at type:%T", s))
	}
	return 0
}

func Int(s interface{}) int64 {
	switch tv := s.(type) {
	case nil:
		return 0
	case int:
		return int64(tv)
	case int64:
		return tv
	case string:
		if i, err := strconv.ParseInt(tv, 10, 64); err != nil {
			log.Panic(err)
		} else {
			return i
		}
	case []byte:
		if i, err := strconv.ParseInt(string(tv), 10, 64); err != nil {
			log.Panic(err)
		} else {
			return i
		}
	case float64:
		return int64(tv)
	default:
		log.Panic(fmt.Sprintf("not impl at type:%T", s))
	}
	panic("not run")
}
func String(val interface{}) string {
	switch tv := val.(type) {
	case nil:
		return ""
	case string:
		return tv
	case int32, int64:
		return fmt.Sprintf("%d", tv)
	case time.Time:
		return tv.Format("2006-01-02 15:04:05")
	case *time.Time:
		return tv.Format("2006-01-02 15:04:05")
	case float32:
		return strconv.FormatFloat(float64(tv), 'f', -1, 64)
	case float64:
		//return fmt.Sprintf("%f", tv)
		return strconv.FormatFloat(tv, 'f', -1, 64)
	case []byte:
		return string(tv)
	default:
		log.Panic(fmt.Errorf("not impl.%T", tv))
	}
	panic("not run")
}
func TruncateTimeZone(tm time.Time) time.Time {
	rev, err := time.Parse("2006-01-02 15:04:05", tm.Format("2006-01-02 15:04:05"))
	if err != nil {
		log.Panic(err)
	}
	return rev
}

//返回单引号包括的字符串
func SignString(s interface{}) string {
	str := String(s)
	return "'" + strings.Replace(str, "'", "''", -1) + "'"
}

//返回单引号包括的字符串,用在sqlx的named中，已经将冒号:转义
func SignStringUseBySqlxNamed(s interface{}) string {
	str := String(s)
	return "'" + strings.Replace(
		strings.Replace(str, "'", "''", -1), ":", "::", -1) + "'"
}
func Float64(s interface{}) float64 {
	switch tv := s.(type) {
	case float32:
		return float64(tv)
	case float64:
		return tv
	case int64:
		return float64(tv)
	case int32:
		return float64(tv)
	case string:
		if f, err := strconv.ParseFloat(tv, 64); err != nil {
			log.Panic(err)
		} else {
			return f
		}
	case []byte:
		if f, err := strconv.ParseFloat(string(tv), 64); err != nil {
			log.Panic(err)
		} else {
			return f
		}
	default:

		log.Panic(fmt.Errorf("%#v can't to float64", s))

	}
	panic("not run")
}
func Bytea(s interface{}) []byte {
	switch tv := s.(type) {
	case nil:
		return nil
	case string:
		return []byte(tv)
	case []byte:
		return tv
	default:
		log.Panic(fmt.Sprintf("not impl at type:%T", s))
	}
	panic("not run")
}
func Strings(s []interface{}) []string {
	result := make([]string, len(s))
	for i, v := range s {
		result[i] = String(v)
	}
	return result
}
func Inter(s []string) []interface{} {
	result := make([]interface{}, len(s))
	for i, v := range s {
		result[i] = v
	}
	return result
}
func Bool(v interface{}) bool {
	switch tv := v.(type) {
	case nil:
		return false
	case bool:
		return tv
	case string:
		if tv == "ON" || tv == "On" || tv == "on" {
			return true
		}
		if tv == "" || tv == "OFF" || tv == "Off" || tv == "off" {
			return false
		}
		if b, err := strconv.ParseBool(tv); err != nil {
			log.Panic(err)
		} else {
			return b
		}
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		return fmt.Sprintf("%d", tv) != "0"
	case float32, float64:
		return fmt.Sprintf("%d", tv) != "0"
	default:
		log.Panic(fmt.Sprintf("not impl at type:%T", v))
	}
	panic("not run")
}
func Split(s string, l string) []string {
	if s == "" {
		return []string{}
	} else {
		return strings.Split(s, l)
	}
}
func StrToDate(s string) (tm time.Time, err error) {
	if len(s) == 8 {
		tm, err = time.Parse("20060102", s)
	} else if len(s) == 10 {
		tm, err = time.Parse("2006-01-02", s)
	} else if s[10] == 'T' {
		tm, err = time.Parse(time.RFC3339, s)
	} else {
		tm, err = time.Parse("2006-01-02 15:04:05.999999999", s)
	}
	return
}
func Date(val interface{}) time.Time {

	switch tv := val.(type) {
	case []byte:
		if tm, err := StrToDate(string(tv)); err != nil {
			log.Panic(err)
		} else {
			return tm
		}
	case string:
		if tm, err := StrToDate(tv); err != nil {
			log.Panic(err)
		} else {
			return tm
		}
	case time.Time:
		return tv
	case *time.Time:
		return *tv
	default:
		log.Panic("error type")
	}
	//不会运行到这句
	return time.Now()
}
