package classification

import (
	"fmt"
	//"qfw/util"
	"regexp"
	"strconv"
	"strings"
	"task"
)

const (
	SPLIT = "___"
)

//var REG_A_RULE = regexp.MustCompile(`([\\+\\|\\(\\)\\^]|[0-9]+)`)

var REG_A_RULE = regexp.MustCompile(`([\\+\\|\\(\\)\\^])`)
var REG_NUM = regexp.MustCompile(`[0-9]+`)

//分类，支持多条规则，返回文本！！！！只提供单条测试
func ClassificationText(text string, rules [][]string) (t string, rs [][]string, rulepos int, res bool) {
	//fmt.Println("rr---", len(rules), len(rules[0]))
	rs = rules
	for n, rule := range rs {
		if len(rule) == 0 || len(rule) > 1 { //规则
			t, rs[n], res = ComputeText(text, rule, 1)
			if res {
				//fmt.Println("规则-----", rule, t, rs, n, res)
				return t, rs, n, res
			}
		} else if len(rule) == 1 { //正则
			r := rule[0]
			rss := []rune(r)
			ru := string(rss[1 : len(rss)-1])
			rulereg, err := regexp.Compile(ru)
			if err != nil {
				continue
			}
			textArr := rulereg.FindAllString(text, -1)
			rs[n] = []string{fmt.Sprintf("<r class='_rf'>%s</r>", ru)}
			if len(textArr) > 0 {
				//fmt.Println("正则---", rulereg, ru)
				rs[n] = []string{fmt.Sprintf("<r class='_rt'>%s</r>", ru)}
				text = strings.Replace(text, textArr[0], fmt.Sprintf("<r class='_and'>%s</r>", textArr[0]), 1)
				return text, rules, n, true
			}
		}
	}
	return
}

func ComputeText(text string, rule []string, num int) (string, []string, bool) {
	var andB, orB, oB []bool
	//fmt.Println("rule----", rule, len(rule))
	op := ""
	for pos := 0; pos < len(rule); pos++ {
		tmp := rule[pos]
		//fmt.Println("---------", pos, "tmp----", tmp, "num----", num, len(rule)-1, pos == len(rule)-1)
		if tmp == "+" || tmp == "^" || tmp == "|" {
			op = tmp
			continue
		} else if REG_NUM.MatchString(tmp) && len(tmp) == 1 {
			continue
		} else {
			tmpresult := false
			if tmp == "(" { //找出子表达式，仅限一层,现在修改为多层逻辑
				tmpexp := []string{}
				pos++
				isRight := 0
				thispos := pos
				for ; pos < len(rule); pos++ {
					//fmt.Println(pos, "rule[pos]===", rule[pos])
					if rule[pos] == "(" {
						isRight++
						tmpexp = append(tmpexp, rule[pos])
					} else if rule[pos] == ")" {
						//fmt.Println("+++++++++isRight", isRight)
						if isRight > 0 {
							isRight--
							tmpexp = append(tmpexp, rule[pos])
						} else {
							num = 1
							if (pos + 1) < len(rule) {
								t := rule[pos+1]
								//fmt.Println("+++++++++数字", t)
								if REG_NUM.MatchString(t) {
									num, _ = strconv.Atoi(t)
								}
							}
							break
						}
					} else {
						tmpexp = append(tmpexp, rule[pos])
					}
				}
				//fmt.Println("1----------------", text)
				//fmt.Println("2----------------", tmpexp)
				text, tmpexp, tmpresult = ComputeText(text, tmpexp, num)
				for tmpos, tmprule := range tmpexp {
					rule[thispos+tmpos] = tmprule
				}
				//fmt.Println("3----------------", rule)
			} else {
				tmpresult = strings.Index(text, tmp) > -1
				//增加对rule的处理
				sclass := "f"
				if tmpresult {
					sclass = "t"
				}
				rule[pos] = fmt.Sprintf("<r class='_r%s'>%s</r>", sclass, tmp)
				//fmt.Println("========", rule[pos])
			}
			if op == "" {
				if (pos+1) < len(rule) && rule[pos+1] == "|" {
					op = "|"
				} else {
					op = "+"
				}
			}
			tclass := ""
			if op == "+" {
				if andB == nil {
					andB = []bool{}
				}
				andB = append(andB, tmpresult)
				tclass = "_and"

			} else if op == "|" {
				if orB == nil {
					orB = []bool{}
				}
				orB = append(orB, tmpresult)
				tclass = "_or"

			} else if op == "^" {
				if oB == nil {
					oB = []bool{}
				}
				oB = append(oB, tmpresult)
				tclass = "_opp"
			}
			//fmt.Println("tclass====", tclass, "---ob", oB, "---orb", orB)
			if tclass != "" && tmp != "(" && tmp != ")" {
				//fmt.Println("text=======", text)
				//fmt.Println("old=======", tmp)
				//fmt.Println("new=======", fmt.Sprintf("<r class='_and'>%s</r>", tmp))
				text = strings.Replace(text, tmp, fmt.Sprintf("<r class='_and'>%s</r>", tmp), 1)
				//fmt.Println("text3=======", text)
			}
		}
	}
	//fmt.Println("textfinish====", text, "num----", num)
	//fmt.Println("匹配个数----", len(orB), CheckBool(orB, "|", num))
	tres := CheckBool(andB, "+", 0) && CheckBool(orB, "|", num) && !CheckBool(oB, "^", 0)
	return text, rule, tres
}

//分类，支持多条规则，有一个满足就返回
func Classification(text string, rules [][]string) (bool, []string) {
	var arr []string
	ok := false
	for _, rule := range rules {
		if len(rule) == 0 || len(rule) > 1 { //规则
			ok, arr = Compute(text, rule, 1)
			if ok {
				return ok, arr
			}
		} else if len(rule) == 1 { //正则
			ruleArr := strings.Split(rule[0], "'")
			rulereg := regexp.MustCompile(ruleArr[1])
			textArr := rulereg.FindAllString(text, -1)
			if len(textArr) > 0 {
				return true, rule
			}
		}
	}
	return ok, arr
}

//规则或者正则识别
func NewAnalyRules(text string, rules []interface{}) (bool, []string) {
	var arr []string
	ok := false
	for _, r := range rules {
		switch r.(type) {
		case string: //规则
			//fmt.Println("规则---", text, r.(string))
			strRuleArr := AnalyRule(r.(string)) //解析规则
			ok, arr = Compute(text, strRuleArr, 1)
			if ok {
				return ok, arr
			}
		case *regexp.Regexp: //正则
			ruleReg := r.(*regexp.Regexp)
			textArr := ruleReg.FindAllString(text, -1)
			//fmt.Println("正则---", text, ruleReg, textArr)
			if len(textArr) > 0 {
				regStr := []string{ruleReg.String()}
				return true, regStr
			}
		default:
			continue
		}
	}
	return ok, arr
}

func AnalyRules(rules []string) [][]string {
	res := [][]string{}
	for i := 0; i < len(rules); i++ {
		if strings.HasPrefix(rules[i], "'") && strings.HasSuffix(rules[i], "'") { //正则
			res = append(res, []string{rules[i]})
		} else { //规则
			res = append(res, AnalyRule(rules[i]))
		}
	}
	return res
}

//解析规则
func AnalyRule(rule string) []string {
	res := []string{}
	ruleNew := REG_A_RULE.ReplaceAllString(rule, fmt.Sprintf("%s${1}%s", SPLIT, SPLIT))
	ruleNewArr := strings.Split(ruleNew, SPLIT)
	for _, key := range ruleNewArr {
		if key != "" {
			res = append(res, key)
			//fmt.Println("规则数组---", res)
		}
	}
	return res
}

//计算
func Compute(text string, rule []string, num int) (bool, []string) {
	var andB, orB, oB []bool
	op := ""
	arr := []string{}
	for pos := 0; pos < len(rule); pos++ {
		tmp := rule[pos]
		if tmp == "+" || tmp == "^" || tmp == "|" {
			op = tmp
			continue
		} else if REG_NUM.MatchString(tmp) && len(tmp) == 1 {
			continue
		} else {
			tmpresult := false
			if tmp == "(" { //找出子表达式，仅限一层,现在修改为多层逻辑
				tmpexp := []string{}
				pos++
				isRight := 0
				for ; pos < len(rule); pos++ {
					if rule[pos] == "(" {
						isRight++
						tmpexp = append(tmpexp, rule[pos])
					} else if rule[pos] == ")" {
						if isRight > 0 {
							isRight--
							tmpexp = append(tmpexp, rule[pos])
						} else {
							num = 1
							if (pos + 1) < len(rule) {
								t := rule[pos+1]
								if REG_NUM.MatchString(t) {
									num, _ = strconv.Atoi(t)
								}
							}
							break
						}
					} else {
						tmpexp = append(tmpexp, rule[pos])
					}
				}
				var arr1 []string
				tmpresult, arr1 = Compute(text, tmpexp, num)
				if len(arr1) > 0 {
					arr = append(arr, arr1...)
				}
			} else {
				tmpresult = strings.Index(text, tmp) > -1
				if op != "^" && tmpresult {
					arr = append(arr, tmp)
				}
			}
			if op == "" {
				if (pos+1) < len(rule) && rule[pos+1] == "|" {
					op = "|"
				} else {
					op = "+"
				}
			}
			if op == "+" {
				if andB == nil {
					andB = []bool{}
				}
				andB = append(andB, tmpresult)

			} else if op == "|" {
				if orB == nil {
					orB = []bool{}
				}
				orB = append(orB, tmpresult)
			} else if op == "^" {
				if oB == nil {
					oB = []bool{}
				}
				oB = append(oB, tmpresult)
			}
		}
	}
	tres := CheckBool(andB, "+", 0) && CheckBool(orB, "|", num) && !CheckBool(oB, "^", 0)
	if !tres {
		arr = []string{}
	}
	return tres, arr
}

func CheckBool(bs []bool, flag string, num int) bool {
	if flag == "+" {
		if bs == nil {
			return true
		} else if len(bs) == 0 {
			return false
		} else {
			b1 := bs[0]
			i := 0
			for _, v := range bs {
				if i > 0 {
					b1 = b1 && v
				}
				i++
			}
			return b1
		}
	} else if flag == "|" {
		if bs == nil {
			return true
		} else if len(bs) == 0 {
			return false
		} else {
			i := 0
			for _, v := range bs {
				if v {
					i++
				}
			}
			return i >= num
		}
	} else {
		if bs == nil {
			return false
		} else if len(bs) == 0 {
			return false
		} else {
			b1 := bs[0]
			i := 0
			for _, v := range bs {
				if i > 0 {
					b1 = b1 || v
				}
				i++
			}
			return b1
		}
	}
}

func ClassText(b, b_reg bool, pos int, s_rule []string, rulearr [][]string, s_con string) (string, [][]string) {
	//util.Debug(b, pos, rulearr, len(s_rule), len(rulearr), s_con)
	ruleMap := make([]map[string]bool, len(rulearr))
	for i, r := range rulearr {
		tmp := map[string]bool{}
		for _, rtmp := range r {
			tmp[rtmp] = true
			if b && i == pos {
				if b_reg {
					reg := regexp.MustCompile(rtmp)
					matchText := reg.FindString(s_con)
					s_con = reg.ReplaceAllString(matchText, "<r class='_and'>"+matchText+"</r>")
				} else {
					s_con = strings.ReplaceAll(s_con, rtmp, "<r class='_and'>"+rtmp+"</r>")
				}
			}
			if !b && pos == -1 {
				if b_reg {
					reg := regexp.MustCompile(rtmp)
					matchText := reg.FindString(s_con)
					s_con = reg.ReplaceAllString(matchText, "<r class='_and'>"+matchText+"</r>")
				} else {
					s_con = strings.ReplaceAll(s_con, rtmp, "<r class='_and'>"+rtmp+"</r>")
				}
			}
		}
		ruleMap[i] = tmp
	}
	//util.Debug("s_con---", len(ruleMap), s_con)
	rules := [][]string{}
	for k, rule := range s_rule {
		tmpRuleArr := strings.Split(rule, "^")
		hasRmWord := len(tmpRuleArr) == 2 //是否有排除词
		ruleResult1 := ""
		for j, tmprule := range tmpRuleArr {
			//util.Debug("tmprule---", tmprule)
			isReg := false
			ruleTextArr := task.REG.FindAllString(tmprule, -1)
			if strings.HasPrefix(tmprule, "'") && strings.HasSuffix(tmprule, "'") { //正则
				tmprule = tmprule[1 : len(tmprule)-1]
				isReg = true
				ruleTextArr = []string{tmprule}
			}
			//util.Debug("ruleTextArr---", ruleTextArr)
			ruleResult2 := ""
			for _, ruleText := range ruleTextArr {
				indexArr := task.REG1.FindAllStringIndex(ruleText, -1)
				//start := indexArr[0][0]
				end := indexArr[0][1]
				ruleText1 := ruleText[1 : end-1]
				if isReg {
					ruleText1 = ruleText
				}
				//util.Debug("ruleText1---", ruleText1)
				tmpArr := []string{}
				for _, t := range strings.Split(ruleText1, "|") {
					if ruleMap[k][t] {
						t = "<r class='_rt'>" + t + "</r>"
					} else {
						t = "<r class='_rf'>" + t + "</r>"
					}
					//util.Debug("t---", t)
					tmpArr = append(tmpArr, t)
				}
				ruleText2 := "(" + strings.Join(tmpArr, "|") + ")"
				//util.Debug("ruleText2---", ruleText2)
				length := len(ruleText)
				if end+1 == length { //有数字
					ruleText2 += string(ruleText[length-1])
				}
				//util.Debug("ruleText2---", ruleText2)
				ruleResult2 += ruleText2
			}
			if hasRmWord && j == 0 {
				ruleResult2 += "^"
			}
			ruleResult1 += ruleResult2
		}
		rules = append(rules, []string{ruleResult1})
	}
	return s_con, rules
}
