package util

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

const (
	conStr = "([\\s\u3000\u2003\u00a0]+|\\\\t)" //所有空格
)

var (
	LReg            = regexp.MustCompile("^" + conStr)
	RReg            = regexp.MustCompile(conStr + "$")
	LRReg           = regexp.MustCompile("^([\\s\u3000\u2003\u00a0]+|\\\\t)|([\\s\u3000\u2003\u00a0]+|\\\\t)$")
	ALLReg          = regexp.MustCompile(conStr)
	LRMReg          = regexp.MustCompile("^([:：]+)|([:：]+)$")
	NoMatchMap      = map[string]bool{} //没有识别出来的标签
	NoMatchMapCount = map[string]int{}  //没有识别出来的标签
	NoMatchMapLock  = &sync.Mutex{}
	PhoneReg        = regexp.MustCompile("((([（(]\\d{3,4}[)）])?(\\d{6,12}([×―—－\\-]+\\d{3,4})?|\\d{3,4}[×―—－\\-]+[\u3000\u2003\u00a0\\s]*\\d{6,12}([×―—－\\-]+\\d{4})?|(\\d{2}[×―—－\\-])+\\d{8}[×―—－\\-](\\d{3}[、])+)(转\\d{3,4})?[或/、,，;；\u3000\u2003\u00a0\\s]*)+(\\d{3,})?)")
	ConvertIntReg_1 = regexp.MustCompile("^[0-9]+[一二三四五六七八九十]+$")
	ConvertIntReg_2 = regexp.MustCompile("^[a-zA-Z0-9\\-]+$")
	ConvertIntReg_3 = regexp.MustCompile("^[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+$")
	ConvertIntReg_4 = regexp.MustCompile("^[①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳]$")
	ConvertIntReg_5 = regexp.MustCompile("^[一二三四五六七八九十]+$")
	ConvertIntReg_6 = regexp.MustCompile("[0-9]+")
	ConvertIntReg_7 = regexp.MustCompile("^" + ConvertIntReg_6.String() + "$")
	//标段号，包号转换
	FindPkgNumReg   = regexp.MustCompile("(\\d[.])+\\d|([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳\\-]+)|(设计|施工|监理|验收)")
	FindPkgNumReg_1 = regexp.MustCompile("设计|施工|监理|验收")
)

func AddtoNoMatchMap(key string) {
	NoMatchMapLock.Lock()
	defer NoMatchMapLock.Unlock()
	NoMatchMapCount[key]++
}

func TrimLeftSpace(con, repl string) string {
	return LReg.ReplaceAllString(con, repl)
}

func TrimRightSpace(con, repl string) string {
	return RReg.ReplaceAllString(con, repl)
}

func TrimLRSpace(con, repl string) string {
	return LRReg.ReplaceAllString(con, repl)
}
func TrimLRAll(con, repl string) string {
	return LRMReg.ReplaceAllString(LRReg.ReplaceAllString(con, repl), repl)
}

// get 网络请求
func Get(apiURL string, params url.Values) (rs []byte, err error) {
	var Url *url.URL
	Url, err = url.Parse(apiURL)
	if err != nil {
		fmt.Printf("解析url错误:\r\n%v", err)
		return nil, err
	}
	//如果参数中有中文参数,这个方法会进行URLEncode
	Url.RawQuery = params.Encode()
	resp, err := http.Get(Url.String())
	if err != nil {
		fmt.Println("err:", err)
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

// post 网络请求 ,params 是url.Values类型
func Post(apiURL string, params url.Values) (rs []byte, err error) {
	resp, err := http.PostForm(apiURL, params)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

//中文数字转换
func ChineseNumberToInt(value string) int {
	result, temp, count := 0, 1, 0
	cnArr := []string{"一", "二", "三", "四", "五", "六", "七", "八", "九"}
	chArr := []string{"十", "百", "千", "万", "亿"}
	for i, v := range []rune(value) {
		b := true //判断是否是chArr
		c := string(v)
		for j, cv := range cnArr { //非单位，即数字
			if c == cv {
				if 0 != count { //添加下一个单位之前，先把上一个单位值添加到结果中
					result += temp
					temp = 1
					count = 0
				}
				// 下标+1，就是对应的值
				temp = j + 1
				b = false
				break
			}
		}
		if b { //单位{'十','百','千','万','亿'}
			for j, cv := range chArr {
				if c == cv {
					b = false
					switch j {
					case 0:
						temp *= 10
						break
					case 1:
						temp *= 100
						break
					case 2:
						temp *= 1000
						break
					case 3:
						temp *= 10000
						break
					case 4:
						temp *= 100000000
						break
					default:
						break
					}
					count++
				}
			}
		}
		if b {
			return -1
		}
		if i == len([]rune(value))-1 { //遍历到最后一个字符
			result += temp
		}
	}
	return result
}

//罗马数字转换
func romeNumberToInt(value string) int {
	for k, v := range []rune("ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ") {
		if value == string(v) {
			return k + 1
		}
	}
	return -1
}

//带圆圈的数字换行
func circleNumberToInt(value string) int {
	for k, v := range []rune("①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳") {
		if value == string(v) {
			return k + 1
		}
	}
	return -1
}

func PackageNumberConvert(val string) string {
	result := val
	for _, value := range strings.Split(val, "/") {
		result = value
		value = ALLReg.ReplaceAllString(value, "")
		if ConvertIntReg_7.MatchString(value) {
			value = strings.TrimLeft(value, "0")
		}
		value = FindPkgNumReg.FindString(value)
		if ConvertIntReg_1.MatchString(value) {
			result = ConvertIntReg_6.FindString(value)
		} else if ConvertIntReg_5.MatchString(value) {
			result = value
			if v := ChineseNumberToInt(value); v != -1 {
				result = strconv.Itoa(v)
				break
			}
		} else if ConvertIntReg_2.MatchString(value) && !strings.HasSuffix(value, "-") {
			result = strings.ToUpper(value)
		} else if ConvertIntReg_3.MatchString(value) {
			if v := romeNumberToInt(value); v != -1 {
				result = strconv.Itoa(v)
				break
			}
		} else if ConvertIntReg_4.MatchString(value) {
			if v := circleNumberToInt(value); v != -1 {
				result = strconv.Itoa(v)
				break
			}
		} else if FindPkgNumReg_1.MatchString(value) {
			result = FindPkgNumReg_1.FindString(value)
		}
	}
	result = strings.Replace(result, ".", "_", -1)
	return result
}

//map中是否存在value
func IsMapHasValue(value interface{}, m interface{}) bool {
	if intStringMap, ok := m.(map[int]string); ok {
		for _, v := range intStringMap {
			if v == value {
				return true
			}
		}
	} else if stringRegMap, ok := m.(map[string]*regexp.Regexp); ok {
		vs, _ := value.(string)
		for _, v := range stringRegMap {
			if v.MatchString(vs) {
				return true
			}
		}
	}
	return false
}

//数组中是否存在value
func IsArrayHasValue(value interface{}, m interface{}) bool {
	if stringArray, ok := m.([]string); ok {
		for _, v := range stringArray {
			if v == value {
				return true
			}
		}
	} else if intArray, ok := m.([]int); ok {
		for _, v := range intArray {
			if v == value {
				return true
			}
		}
	}
	return false
}

//获取map中第一个key的值
func FirstKeyValueInMap(m interface{}) (string, interface{}) {
	if mv, ok := m.(map[string]*Tag); ok {
		for k, v := range mv {
			return k, v.Weight
		}
	} else if mv, ok := m.(map[string][]*Tag); ok {
		for k, v := range mv {
			if len(v) > 0 {
				return k, v[0].Weight
			}
			return k, 0
		}
	} else if mv, ok := m.(map[string]string); ok {
		for k, v := range mv {
			return k, v
		}
	} else if mv, ok := m.(map[int]string); ok {
		for k, v := range mv {
			return strconv.Itoa(k), v
		}
	}
	return "", nil
}
