package utils

import (
	"fmt"
	"math/rand"
	"reflect"
	"regexp"
	"sort"
	"strconv"
)

const (
	IPV4Re      = `^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`
	IpV6Re      = `^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$`
	NameTypeRe  = `^\S*\.$`
	LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
)

func RandStringBytes(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = LetterBytes[rand.Intn(len(LetterBytes))]
	}
	return string(b)
}

func GetPage(page int, pageSize int) int {
	result := 0
	if page > 0 && pageSize > 0 {
		result = (page - 1) * pageSize
	}

	return result
}

func Split(s rune) bool {
	if s == '-' {
		return true
	}
	return false
}

// CheckDnsRecordValue 检测 DNS target 是否合法
func CheckDnsRecordValue(dType string, target string) (err error) {
	if dType == "A" {
		matched, _ := regexp.MatchString(IPV4Re, target)
		if !matched {
			err = fmt.Errorf("记录值必须是合法 IPv4 地址")
			return
		}
	} else if dType == "CNAME" || dType == "MX" || dType == "NS" {
		matched, _ := regexp.MatchString(NameTypeRe, target)
		if !matched {
			err = fmt.Errorf("记录值必须是 NameType 形式，以 .结尾，如：www.example.com. ")
			return
		}
	} else if dType == "TXT" {
		if len(target) > 512 {
			err = fmt.Errorf("记录值必须是合法字符：大小写字母，数字,空格，及以下字符：-~=:;/.@+^!*, 且长度不能超过 512")
			return
		}
	} else if dType == "AAAA" {
		matched, _ := regexp.MatchString(IpV6Re, target)
		if !matched {
			err = fmt.Errorf("记录值必须是合法 IPv6 地址")
			return
		}

	}

	return nil
}

type BodyWrapper struct {
	Items []interface{}
	By    func(p, q *interface{}) bool //内部 Less() 函数会用到
}

func (bw BodyWrapper) Len() int { // 重写 Len() 方法
	return len(bw.Items)
}

func (bw BodyWrapper) Swap(i, j int) { // 重写 Swap() 方法
	bw.Items[i], bw.Items[j] = bw.Items[j], bw.Items[i]
}

func (bw BodyWrapper) Less(i, j int) bool { // 重写 Less() 方法
	return bw.By(&bw.Items[i], &bw.Items[j])
}

// SortBodyByIndexDesc sorts the items by the index in descending order. 降序
func SortBodyByIndexDesc(items []interface{}, index int) {
	sort.Sort(BodyWrapper{items, func(p, q *interface{}) bool {
		v := reflect.ValueOf(*p)
		i := v.FieldByIndex([]int{index})
		v = reflect.ValueOf(*q)
		j := v.FieldByIndex([]int{index})
		if a, err := strconv.ParseFloat(i.String(), 64); err == nil {
			if b, err := strconv.ParseFloat(j.String(), 64); err == nil {
				return a > b
			}
		} else if i.Kind().String() == "float32" {
			return i.Float() > j.Float()
		} else if i.Kind().String() == "float64" {
			return i.Float() > j.Float()
		} else if i.Kind().String() == "int" {
			return i.Int() > j.Int()
		}
		return i.String() < j.String()
	}})
}

// SortBodyByIndexAsc sorts the items by the index in ascending order. 升序
func SortBodyByIndexAsc(items []interface{}, index int) {
	sort.Sort(BodyWrapper{items, func(p, q *interface{}) bool {
		v := reflect.ValueOf(*p)
		i := v.FieldByIndex([]int{index})
		v = reflect.ValueOf(*q)
		j := v.FieldByIndex([]int{index})
		if a, err := strconv.ParseFloat(i.String(), 64); err == nil {
			if b, err := strconv.ParseFloat(j.String(), 64); err == nil {
				return a < b
			}
		} else if i.Kind().String() == "float32" {
			return i.Float() < j.Float()
		} else if i.Kind().String() == "float64" {
			return i.Float() < j.Float()
		} else if i.Kind().String() == "int" {
			return i.Int() < j.Int()
		}
		return i.String() > j.String()
	}})
}
