package otherutils

import (
	"regexp"
	"strconv"
	"strings"
	"time"
)

//城市编号对应关系
/*var code_and_city = [][]string{{"11", "北京"}, {"12", "天津"},
{"13", "河北"}, {"14", "山西"}, {"15", "内蒙古"}, {"21", "辽宁"},
{"22", "吉林"}, {"23", "黑龙江"}, {"31", "上海"}, {"32", "江苏"},
{"33", "浙江"}, {"34", "安徽"}, {"35", "福建"}, {"36", "江西"},
{"37", "山东"}, {"41", "河南"}, {"42", "湖北"}, {"43", "湖南"},
{"44", "广东"}, {"45", "广西"}, {"46", "海南"}, {"50", "重庆"},
{"51", "四川"}, {"52", "贵州"}, {"53", "云南"}, {"54", "西藏"},
{"61", "陕西"}, {"62", "甘肃"}, {"63", "青海"}, {"64", "宁夏"},
{"65", "新疆"}, {"71", "台湾"}, {"81", "香港"}, {"82", "澳门"},
{"91", "国外"}}
*/

//城市编号
var code_citys = []string{"11", "12", "13", "14", "15", "21", "22",
	"23", "31", "32", "33", "34", "35", "36", "37", "41", "42", "43",
	"44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63",
	"64", "65", "71", "81", "82", "91"}

//每位加权因子
var powers = []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}

//第18位校检码
var verifyCode = []string{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}

// 将15位身份证转换为18位
func convertIdcarBy15Bit(idcard string) string {
	if len(idcard) != 15 {
		return ""
	}

	if !isDigital(idcard) {
		return ""
	}
	//130503 670401 001
	idcard17 := idcard[:6] + "19" + idcard[6:]

	checkCode := checkCode(idcard17)
	if len(checkCode) == 0 {
		return ""
	}
	idcard17 += checkCode

	return idcard17
}

//将和值与11取模得到余数进行校验码判断
func getCheckCodeBySum(sum17 int) string {
	switch sum17 % 11 {
	case 10:
		return "2"
	case 9:
		return "3"
	case 8:
		return "4"
	case 7:
		return "5"
	case 6:
		return "6"
	case 5:
		return "7"
	case 4:
		return "8"
	case 3:
		return "9"
	case 2:
		return "x"
	case 1:
		return "0"
	case 0:
		return "1"
	}
	return ""
}

//判断是否为数字
func isDigital(str string) bool {
	var validID = regexp.MustCompile(`^[0-9]*$`)
	return validID.MatchString(str)
}

//判断18位身份证的合法性
func isValidate18Idcard(idcard string) bool {
	if len(idcard) != 18 {
		return false
	}

	idcard17 := idcard[:17]
	idcard18Code := idcard[17:18]
	//判断前17位是否都是数字
	if !isDigital(idcard17) {
		return false
	}

	//判断前两位是否合法
	card_pre_val := false
	card_pre := idcard17[:2]
	for _, code_city := range code_citys {
		if code_city == card_pre {
			card_pre_val = true
		}
	}
	if !card_pre_val {
		return false
	}

	//计算加权因子
	checkCode := checkCode(idcard17)
	if len(checkCode) == 0 {
		return false
	}
	if strings.EqualFold(idcard18Code, checkCode) {
		return true
	}
	return false
}

//计算加权因子
func checkCode(idcard17 string) string {
	//将身份证的每位和对应位的加权因子相乘之后，再得到和值
	if len(idcard17) != len(powers) {
		return ""
	}
	sum17 := 0
	for i := range idcard17 {
		char_int, _ := strconv.Atoi(idcard17[i : i+1])
		sum17 = sum17 + char_int*powers[i]
	}

	return getCheckCodeBySum(sum17)
}

//验证所有的身份证的合法性
func ValidatedAllIdCard(idcard string) bool {
	if len(idcard) == 15 {
		idcard = convertIdcarBy15Bit(idcard)
	}
	if len(idcard) > 0 {
		return isValidate18Idcard(idcard)
	}
	return false
}

// 是否为防沉迷账号
// cardId 身份证号
// indulgeage 防沉迷年龄 to indulge in; to wallow in; to revel in
func GetAge(cardId string) int {
	//, indulgeage int
	if !ValidatedAllIdCard(cardId) {
		return 0
	}

	// 判断年龄
	birthDay, err := strconv.Atoi(cardId[6:14])
	if err != nil {
		return 0
	}
	now_time := time.Now()
	ct := now_time.Year()*10000 + int(now_time.Month())*100 + now_time.Day()
	return (ct - birthDay) / 10000
}

//验证是否为中文
func CheckZh_cn(str string) bool {
	if len(str) < 1 {
		return false
	}

	var hzRegexp = regexp.MustCompile("^[\u4E00-\u9FA5]+$")
	return hzRegexp.MatchString(str)
}
