package common

import (
	"crypto/md5"
	"encoding/hex"
	"math"
	"strings"
)

//安全锁
//func SafeMutex(tag int, f func() interface{}) interface{} {
//
//	mutexer.Lock()
//	if mutex[tag] == nil {
//
//		mutex[tag] = &sync.RWMutex{}
//
//	}
//	mutexer.Unlock()
//
//	mutex[tag].Lock()
//	res := f()
//	mutex[tag].Unlock()
//	return res
//}

// StrFirstToUpper 字符串首字符大写
func StrFirstToUpper(str string) string {
	if len(str) == 0 {
		return str
	}

	first := Substr(str, 0, 1)
	other := Substr(str, 1, len(str)-1)

	return strings.ToUpper(first) + other
}

// StrLd 相似度计算 ld compares two strings and returns the levenshtein distance between them.
func StrLd(s, t string, ignoreCase bool) int {
	if ignoreCase {
		s = strings.ToLower(s)
		t = strings.ToLower(t)
	}
	d := make([][]int, len(s)+1)
	for i := range d {
		d[i] = make([]int, len(t)+1)
	}
	for i := range d {
		d[i][0] = i
	}
	for j := range d[0] {
		d[0][j] = j
	}
	for j := 1; j <= len(t); j++ {
		for i := 1; i <= len(s); i++ {
			if s[i-1] == t[j-1] {
				d[i][j] = d[i-1][j-1]
			} else {
				min := d[i-1][j]
				if d[i][j-1] < min {
					min = d[i][j-1]
				}
				if d[i-1][j-1] < min {
					min = d[i-1][j-1]
				}
				d[i][j] = min + 1
			}
		}

	}
	return d[len(s)][len(t)]
}

// Substr 字符串截取
func Substr(str string, start int, length int) string {
	rs := []rune(str)
	rl := len(rs)
	end := 0

	if start < 0 {
		start = rl - 1 + start
	}
	end = start + length

	if start > end {
		start, end = end, start
	}

	if start < 0 {
		start = 0
	}
	if start > rl {
		start = rl
	}
	if end < 0 {
		end = 0
	}
	if end > rl {
		end = rl
	}

	return string(rs[start:end])
}

// IndexLastStr 获取最后出现字符串的下标
//return  找不到返回 -1
func IndexLastStr(str, sep string) int {
	sepSlice := []rune(sep)
	strSlice := []rune(str)
	if len(sepSlice) > len(strSlice) {
		return -1
	}

	v := sepSlice[len(sepSlice)-1]

	for i := len(strSlice) - 1; i >= 0; i-- {
		vs := strSlice[i]
		if v == vs {
			j := len(sepSlice) - 2
			for ; j >= 0; j-- {
				vj := sepSlice[j]
				vsj := strSlice[i-(len(sepSlice)-j-1)]
				if vj != vsj {
					break
				}
			}
			if j < 0 {
				return i - len(sepSlice) + 1
			}
		}

	}
	return -1
}

// Md5 md5
func Md5(req string) string {
	md5Ctx := md5.New()
	md5Ctx.Write([]byte(req))
	cipherStr := md5Ctx.Sum(nil)
	return hex.EncodeToString(cipherStr)
}

// Rand 随机数
func Rand(count int) int {
	res := Random()
	for i := 0; i < count; i++ {
		res = res * 10
	}
	return ObjToInt(res)
}
func Random() float64 {
	v := float64(0)
	m := float64(0.1)
	for i := 0; i < 15; i++ {
		facter := map[int]int{4: 1, 9: 1, 2: 1, 3: 1, 1: 1, 7: 1, 0: 1, 5: 1, 6: 1, 8: 1}
		for k, _ := range facter {

			v = v + float64(k)*m
			break
		}
		m = m * 0.1
	}

	return v

}

// RandX 随机数范围
func RandX(small int, max int) int {
	res := 0
	//随机对象
	if small == max {
		return small
	}

	for {
		res = ObjToInt(Random() * float64(max+1))
		if res >= small {
			break
		}
	}
	return res
}

//
////路由
//func Router(ctr CtrInterface) {
//
//	str := reflect.ValueOf(ctr).Type().String()
//	a := strings.IndexByte(str, '.')
//
//	c := len(str) - len("Ctr") - 1
//
//	app := Substr(str, 0, a)    //属于哪个app
//	ct := Substr(str, a+1, c-a) //属于哪个控制器
//	var x = map[string]CtrInterface{}
//	if _, ok := Proj[app]; ok {
//		//存在APP
//		x = Proj[app]
//	} else {
//		x = map[string]CtrInterface{}
//	}
//	x[ct] = ctr //将控制器存入APP
//	//	fmt.Println(c)
//	Proj[app] = x //将APP存入测试
//}
//
//func RunMethodListener(test func(app []string)) {
//	RunMethodListenerFunc = test
//}

//func SetDb(db *sql.DB) {
//	db.SetMaxOpenConns(2000)
//	db.SetMaxIdleConns(1000)
//	db.Ping()
//	SqlDB = &*db
//	GetDb()
//}

// DeepCopyMap 复制返回数组
func DeepCopyMap(value interface{}) interface{} {
	if valueMap, ok := value.(Map); ok {
		newMap := make(Map)
		for k, v := range valueMap {
			newMap[k] = DeepCopyMap(v)
		}

		return newMap
	} else if valueSlice, ok := value.([]interface{}); ok {
		newSlice := make([]interface{}, len(valueSlice))
		for k, v := range valueSlice {
			newSlice[k] = DeepCopyMap(v)
		}

		return newSlice
	} else if valueMap, ok := value.(map[string]interface{}); ok {
		newMap := make(map[string]interface{})
		for k, v := range valueMap {
			newMap[k] = DeepCopyMap(v)
		}

		return newMap

	} else if valueSlice, ok := value.(Slice); ok {
		newSlice := make(Slice, len(valueSlice))
		for k, v := range valueSlice {
			newSlice[k] = DeepCopyMap(v)
		}

		return newSlice
	}

	return value
}

////获取数据库
//func GetDb() (HoTimeDB, error) {
//	Db.DB = &*SqlDB
//	Db.Cached = true
//	return Db, nil
//}

//初始化方法
//func Init() {
//
//	http.HandleFunc("/", PublicCore.myHandler)
//
//	InitCache()
//	http.ListenAndServe(":"+Config["port"].(string), nil)
//}

////设置Config
//func SetCfg(tData Map) {
//	for k, v := range tData {
//		Config[k] = v
//	}
//}

// Round 浮点数四舍五入保留小数
func Round(f float64, n int) float64 {
	pow10_n := math.Pow10(n)
	return math.Trunc((f+0.5/pow10_n)*pow10_n) / pow10_n
}

//func InitDbCache(tim int64) {
//	res := Db.Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='" + Config.GetString("dbName") + "' AND TABLE_NAME='cached'")
//	if len(res) == 0 {
//		Db.Exec("CREATE TABLE `cached` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `ckey` varchar(60) DEFAULT NULL, `cvalue` varchar(2000) DEFAULT NULL, `time` bigint(20) DEFAULT NULL, `endtime` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=198740 DEFAULT CHARSET=utf8")
//	}
//	cacheConfig := Config.GetMap("cacheConfig").GetObj("db").(CacheConfg)
//	cacheConfig.Used = true
//	if tim != 0 {
//		cacheConfig.Time = tim
//	}
//	Config.GetMap("cacheConfig")["db"] = cacheConfig
//}
//
//func Cache(key interface{}, data ...interface{}) interface{} {
//	cachePRI := Config["cachePRI"].([]string)
//	var res interface{}
//	for i := 0; i < len(cachePRI); i++ {
//		if cachePRI[i] == "ridis" && Config["cacheConfig"].(Map)["ridis"].(CacheConfg).Used {
//			res = CacheMemIns.Cache(ObjToStr(key), data...)
//		}
//		if cachePRI[i] == "db" && Config["cacheConfig"].(Map)["db"].(CacheConfg).Used {
//			res = CacheDBIns.Cache(ObjToStr(key), data...)
//		}
//		if cachePRI[i] == "memory" && Config["cacheConfig"].(Map)["memory"].(CacheConfg).Used {
//			res = CacheMemIns.Cache(ObjToStr(key), data...)
//		}
//		//将缓存送到前面的可缓存仓库去
//		if res != nil {
//			for j := 0; j < i; j++ {
//				if cachePRI[j] == "ridis" && Config["cacheConfig"].(Map)["ridis"].(CacheConfg).Used {
//					CacheMemIns.Cache(ObjToStr(key), res)
//				}
//				if cachePRI[j] == "db" && Config["cacheConfig"].(Map)["db"].(CacheConfg).Used {
//					CacheDBIns.Cache(ObjToStr(key), res)
//				}
//				if cachePRI[j] == "memory" && Config["cacheConfig"].(Map)["memory"].(CacheConfg).Used {
//					CacheMemIns.Cache(ObjToStr(key), res)
//				}
//
//			}
//			break
//		}
//
//	}
//	return res
//}

//func InitCache() {
//	CacheMemIns.Init(Config["cacheConfig"].(Map)["memory"].(CacheConfg).Time)
//	CacheDBIns.Init(Config["cacheConfig"].(Map)["db"].(CacheConfg).Time)
//}
