package utils

import (
	"bytes"
	"compress/flate"
	"encoding/json"
	"fmt"
	"goutil/logUtilPlus"
	"io/ioutil"
	"math/rand"
	"net/http"
	"runtime/debug"
	"strconv"
	"strings"
	"time"
)

// 定义常量
var MinDateTime = time.Date(2000, 1, 1, 0, 0, 0, 0, time.Local)
var MaxDateTime = time.Date(3000, 1, 1, 0, 0, 0, 0, time.Local)
var GuidEmpty = "00000000-0000-0000-0000-000000000000"

// IsTrue
// 	@description: 是否为true
// parameter:
//	@data: []byte格式的bool信息
// return:
//	@bool: 返回布尔值
func IsTrue(data []byte) bool {

	if data == nil {
		return false
	}

	if len(data) == 0 {
		return false
	}

	if data[0] == 0 {
		return false
	} else {
		return true
	}
}

// ConvertBooleanToBytes
// 	@description: bool型转换成byte数组
// parameter:
//	@status: 状态
// return:
//	@[]byte: 返回字节数组
func ConvertBooleanToBytes(status bool) []byte {

	if status == false {
		return []byte{0}
	} else {
		return []byte{1}
	}
}

// StrSliceJoinToStr
// 	@description: 将[]string组装成字符串
// parameter:
//	@numArray: 源int32数组
//	@sep: 分割字符串
// return:
//	@string: 组成的字符串
func StrSliceJoinToStr(numArray []string, sep string) string {
	str := ""
	if numArray == nil || len(numArray) == 0 {
		return str
	}

	for _, n := range numArray {
		str += fmt.Sprintf("%s%s", n, sep)
	}

	str = strings.TrimSuffix(str, sep)

	return str
}

// Int32SliceJoinToStr
// 	@description: 将[]int32转换成字符串
// parameter:
//	@source: 资源
//	@sep: 分隔符
// return:
//	@result: 字符串
func Int32SliceJoinToStr(source []int32, sep string) (result string) {
	if source == nil || len(source) == 0 {
		return ""
	}

	for _, s := range source {
		result += fmt.Sprintf("%d%s", s, sep)
	}

	result = strings.TrimRight(result, sep)

	return
}

// SplitToStrSlice
// 	@description: 将字符串切割为[]string
// parameter:
//	@s: 输入字符串
//	@sep: 分割字符串
//	@removeEmpty: 是否去除空字符串
// return:
//	@resultSlice: 字符串列表
func SplitToStrSlice(s, sep string, removeEmpty bool) (resultSlice []string) {
	if len(s) == 0 {
		return make([]string, 0)
	}

	// 先按照分隔符进行切割
	strSlice := strings.Split(s, sep)

	for _, value := range strSlice {
		if removeEmpty {
			// 去除空格
			if value = strings.TrimSpace(value); value == "" {
				continue
			}
		}

		resultSlice = append(resultSlice, value)
	}

	return resultSlice
}

// ParseTimeString
// 	@description: 解析时间字符串
// parameter:
//	@timeStr: 时间字符串，例：12:33:12
// return:
//	@hour: 小时
//	@minute: 分钟
//	@second: 秒数
func ParseTimeString(timeStr string) (hour int, minute int, second int) {
	timeSlice := strings.Split(timeStr, ":")
	if len(timeSlice) != 3 {
		return
	}

	hour, _ = strconv.Atoi(timeSlice[0])
	minute, _ = strconv.Atoi(timeSlice[1])
	second, _ = strconv.Atoi(timeSlice[2])

	return
}

// Rm_duplicate_string
// 	@description: 去重
// parameter:
//	@list: 列表
// return:
//	@[]string: 去重后的数据
func Rm_duplicate_string(list []string) []string {
	var x []string = []string{}
	for _, i := range list {
		if len(x) == 0 {
			x = append(x, i)
		} else {
			for k, v := range x {
				if i == v {
					break
				}
				if k == len(x)-1 {
					x = append(x, i)
				}
			}
		}
	}
	return x
}

// Rm_duplicate_int32
// 	@description: 去重
// parameter:
//	@list: 列表数据
// return:
//	@[]int32: 去重后的结果
func Rm_duplicate_int32(list []int32) []int32 {
	var x []int32 = []int32{}
	for _, i := range list {
		if len(x) == 0 {
			x = append(x, i)
		} else {
			for k, v := range x {
				if i == v {
					break
				}
				if k == len(x)-1 {
					x = append(x, i)
				}
			}
		}
	}
	return x
}

// RandomAarrayOfInt32
// 	@description: int32数组乱序
// parameter:
//	@arr: 数组
// return:
func RandomAarrayOfInt32(arr []int32) {

	if arr == nil {
		return
	}

	if len(arr) <= 0 {
		return
	}

	rand.Seed(time.Now().UnixNano())

	for i := len(arr) - 1; i > 0; i-- {
		num := rand.Intn(i + 1)
		arr[i], arr[num] = arr[num], arr[i]
	}
}

// RandomAarrayOfString
// 	@description: string数组乱序
// parameter:
//	@arr: 数组
// return:
func RandomAarrayOfString(arr []string) {

	if arr == nil {
		return
	}

	if len(arr) <= 0 {
		return
	}

	rand.Seed(time.Now().UnixNano())

	for i := len(arr) - 1; i > 0; i-- {
		num := rand.Intn(i + 1)
		arr[i], arr[num] = arr[num], arr[i]
	}
}

// LogErrorRecover
// 	@description: 记录错误
// parameter:
// return:
func LogErrorRecover() {
	if err := recover(); err != nil {
		tmsg := fmt.Sprintf("err msg:%s  stack:%s", err, debug.Stack())
		logUtilPlus.ErrorLog(tmsg)
	}
}

// LogReqErrorRecover
// 	@description: 记录错误
// parameter:
//	@r:
// return:
func LogReqErrorRecover(r *http.Request) {
	if err := recover(); err != nil {
		b, err := json.Marshal(r)
		reqStr := ""
		if err == nil {
			reqStr = string(b)
		}
		tmsg := fmt.Sprintf("RequestInfo:%s .err msg:%s  stack:%s", reqStr, err, debug.Stack())
		logUtilPlus.ErrorLog(tmsg)
	}
}

// StringSliceIsExists
// 	@description: StringSliceIsExists
// parameter:
//	@strList: strList
//	@val: val
// return:
//	@bool: 是否存在
func StringSliceIsExists(strList []string, val string) bool {

	if strList == nil {
		return false
	}

	for _, v := range strList {
		if v == val {
			return true
		}
	}

	return false
}

// Int64SliceIsExists
// 	@description: Int64SliceIsExists
// parameter:
//	@strList: strList
//	@val: val
// return:
//	@bool: 是否存在
func Int64SliceIsExists(strList []int64, val int64) bool {

	if strList == nil {
		return false
	}

	for _, v := range strList {
		if v == val {
			return true
		}
	}

	return false
}

// SliceIsExists
// 	@description: SliceIsExists
// parameter:
//	@n: n
//	@f: f
// return:
//	@bool: 是否存在
func SliceIsExists(n int, f func(int) bool) bool {

	for i := 0; i < n; i++ {
		if f(i) {
			return true
		}
	}

	return false
}

// FlateEncode
// 	@description: 压缩字符串
// parameter:
//	@input: 输入字符列表
// return:
//	@result: 结果字符列表
//	@err: 错误信息
func FlateEncode(input []byte) (result []byte, err error) {
	var buf bytes.Buffer
	w, err := flate.NewWriter(&buf, flate.DefaultCompression)
	if err != nil {
		return nil, err
	}

	// 无法使用defer close使用无法拿到结果
	_, err = w.Write(input)
	if err != nil {
		return nil, err
	}

	w.Close()

	result = buf.Bytes()
	return
}

// FlateDecode
// 	@description: FlateDecode
// parameter:
//	@input: 输入字符列表
// return:
//	@result: 结果字符列表
//	@err: 错误信息
func FlateDecode(input []byte) (result []byte, err error) {
	result, err = ioutil.ReadAll(flate.NewReader(bytes.NewReader(input)))
	return
}
