package services

import (
	"fmt"
	"hongze/hongze_cygx/models"
	"math/rand"
	"reflect"
	"sort"
	"time"
)

func MakeTree(allNode []*models.CygxIndustryMapItems, node *models.CygxIndustryMapItems) {
	childs, _ := haveChild(allNode, node) //判断节点是否有子节点并返回
	if len(childs) > 0 {
		node.Children = append(node.Children, childs[0:]...) //添加子节点
		for _, v := range childs {                           //查询子节点的子节点，并添加到子节点
			_, has := haveChild(allNode, v)
			if has {
				MakeTree(allNode, v) //递归添加节点
			}
		}
	}
}

func haveChild(allNode []*models.CygxIndustryMapItems, node *models.CygxIndustryMapItems) (childs []*models.CygxIndustryMapItems, yes bool) {
	for _, v := range allNode {
		if v.ParentId == node.IndustryMapId {
			childs = append(childs, v)
		}
	}
	if len(childs) > 0 {
		yes = true
	}
	return
}

func GetIndustryMap() {
	list, err := models.GetCygxIndustryMapByParentId(0)
	if err != nil {
		return
	}
	rootNode := list[0]
	allNodes, err := models.GetCygxIndustryMapAll()
	if err != nil {
		return
	}
	MakeTree(allNodes, rootNode)
}

func GetIndustryTree() (rootNode *models.CygxIndustryMapItems, err error) {
	//fmt.Println("start")
	list, err := models.GetCygxIndustryMapByParentId(0)
	if err != nil {
		return
	}
	rootNode = list[0]
	allNodes, err := models.GetCygxIndustryMapAll()
	if err != nil {
		return
	}
	MakeTree(allNodes, rootNode)
	//resultJson,err:=json.Marshal(rootNode)
	//fmt.Println("Err:",err)
	//fmt.Println("allNodes:",string(resultJson))
	//utils.FileLog.Info("allNodes:%s",string(resultJson))
	//fmt.Println("end")
	return
}

//获取对应的层级map
func getMap(tree *models.CygxIndustryMapItems, item *models.CygxIndustryMapItems, hasIdMap map[int]string, otherChildMapSlice map[int][]*models.CygxIndustryMapItems) {
	//深度
	depth := 1

	//获取下级
	childTree := getChildTree(tree, item)
	depth = childTreeToSlice(childTree, hasIdMap, depth, otherChildMapSlice)

	//获取上级
	var tmpParentSlice []*models.CygxIndustryMapItems
	tmpParentSlice, _ = parentTreeToSlice(tree, item, 0, tmpParentSlice, hasIdMap)
	//移除第一个最上级的行业（根节点）
	tmpParentSlice = append(tmpParentSlice[:0], tmpParentSlice[1:len(tmpParentSlice)]...)
	//切片反转
	tmpParentSlice = reverse(tmpParentSlice)
	for _, v := range tmpParentSlice {
		depth++
		if _, ok := hasIdMap[v.IndustryMapId]; ok == false {
			otherChildMapSlice[depth] = append(otherChildMapSlice[depth], v)
		}
	}

	//获取同级
	//fmt.Println("===============")
	depth = siblingTreeToSlice(tree, item, hasIdMap, depth, otherChildMapSlice)

	//上级的同级~
	/*for _,parentSlice := range tmpParentSlice{
		depth = siblingTreeToSlice(tree,parentSlice,hasIdMap,depth,otherChildMapSlice)
	}*/
	return
}

//获取行业图谱切片
func GetIndustryMapNameSlice(industryName string) (nameSlice []string, err error) {
	nameSlice = append(nameSlice, industryName)
	tree, err := GetIndustryTree()
	if err != nil {
		return
	}
	//已经存在的行业id的map集合
	hasIdMap := make(map[int]string)
	itemList, err := models.GetFirstCygxIndustryListByName(industryName)
	if err != nil {
		return
	}
	//找不到对应的数据
	if len(itemList) <= 0 {
		return
	}

	industryMapList := make(map[int][]*models.CygxIndustryMapItems)
	for _, item := range itemList {
		industryMapList[item.Level] = append(industryMapList[item.Level], item)
	}

	//将查出来的根节点数据的key取出来，放在切片中，并对该切片做正序排列
	var sortIndustryList []int
	for k, _ := range industryMapList {
		sortIndustryList = append(sortIndustryList, k)
	}
	sort.Ints(sortIndustryList)

	//最底层节点的数据集合
	list := industryMapList[sortIndustryList[0]]

	otherChildMapSlice := map[int][]*models.CygxIndustryMapItems{}
	for _, item := range list {
		hasIdMap[item.IndustryMapId] = ""
		//将自己的节点给加进去
		otherChildMapSlice[0] = append(otherChildMapSlice[0], item)
		getMap(tree, item, hasIdMap, otherChildMapSlice)
	}
	var tmpSlice []*models.CygxIndustryMapItems

	//将其他规律数据的key取出来，放在切片中，并对该切片做正序排列
	var sortList []int
	for k, _ := range otherChildMapSlice {
		sortList = append(sortList, k)
	}
	sort.Ints(sortList)

	//遍历该切片，根据下标key获取对应的数据，并插入到主数据中
	for _, v := range sortList {
		tmpChildSlice := otherChildMapSlice[v]
		randSlice(tmpChildSlice)
		tmpSlice = append(tmpSlice, tmpChildSlice...)
		//fmt.Println(k,"=====")
		//for _,tmpV := range otherChildMapSlice[v]{
		//	fmt.Println(tmpV.IndustryMapName)
		//}
	}
	//名字切片
	for _, v := range tmpSlice {
		//fmt.Println("k===",k,"=======v=======",v)
		nameSlice = append(nameSlice, v.IndustryMapName)
	}

	//fmt.Println(nameSlice)
	//fmt.Println(strings.Join(nameSlice,","))
	//utils.FileLog.Info("allNodes:%s",strings.Join(nameSlice,","))
	return
}

//切片反转
func reverse(s []*models.CygxIndustryMapItems) []*models.CygxIndustryMapItems {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
	return s
}

//获取当前节点的树
func getChildTree(rootNode *models.CygxIndustryMapItems, nowNode *models.CygxIndustryMapItems) (returnNode *models.CygxIndustryMapItems) {
	if rootNode.IndustryMapId == nowNode.IndustryMapId {
		returnNode = rootNode
		return
	}
	if rootNode.Children != nil {
		for _, v := range rootNode.Children {
			if v.IndustryMapId == nowNode.IndustryMapId {
				returnNode = v
			} else {
				returnNode = getChildTree(v, nowNode)
			}
			if returnNode != nil {
				return
			}
		}
	}
	return
}

//获取子树V2，与上一个子树规律不一样，因为上级
func childTreeToSlice(rootNode *models.CygxIndustryMapItems, hasIdMap map[int]string, depth int, otherChildMapSlice map[int][]*models.CygxIndustryMapItems) (maxDepth int) {
	if rootNode.Children != nil {
		depth++
		maxDepth = depth
		for _, v := range rootNode.Children {
			//判断是否已经录入，如果已经录入，那么不处理
			if _, ok := hasIdMap[v.IndustryMapId]; ok == false {
				otherChildMapSlice[depth] = append(otherChildMapSlice[depth], v)
			}
		}

		for _, v := range rootNode.Children {
			//判断是否已经录入，如果已经录入，那么不处理
			if _, ok := hasIdMap[v.IndustryMapId]; ok == false {
				hasIdMap[v.IndustryMapId] = ""
				returnDepth := childTreeToSlice(v, hasIdMap, depth, otherChildMapSlice)
				if returnDepth > maxDepth {
					maxDepth = returnDepth
				}
			}
		}
	}
	return maxDepth
}

//获取兄弟级树
func siblingTreeToSlice(rootNode *models.CygxIndustryMapItems, nowNode *models.CygxIndustryMapItems, hasIdMap map[int]string, depth int, otherChildMapSlice map[int][]*models.CygxIndustryMapItems) (maxDepth int) {
	if rootNode.Children != nil {
		depth++
		maxDepth = depth
		for _, v := range rootNode.Children {
			//如果父级id一致的情况下，那么代表这是兄弟节点或者是自己了
			if v.ParentId == nowNode.ParentId {
				//判断是否已经录入，如果已经录入，那么不处理
				if _, ok := hasIdMap[v.IndustryMapId]; ok == false {
					otherChildMapSlice[depth] = append(otherChildMapSlice[depth], v)
					returnDepth := childTreeToSlice(v, hasIdMap, depth, otherChildMapSlice)
					if returnDepth > maxDepth {
						maxDepth = returnDepth
					}
				}
			} else {
				returnDepth := siblingTreeToSlice(v, nowNode, hasIdMap, depth, otherChildMapSlice)
				if returnDepth > maxDepth {
					maxDepth = returnDepth
				}
			}
		}

		for _, v := range rootNode.Children {
			if v.ParentId == nowNode.ParentId {
				if _, ok := hasIdMap[v.IndustryMapId]; ok == false {
					hasIdMap[v.IndustryMapId] = ""
				}

			}
		}
	}
	return
}

//获取上级树
func parentTreeToSlice(rootNode *models.CygxIndustryMapItems, nowNode *models.CygxIndustryMapItems, depth int, tmpReturnSlice []*models.CygxIndustryMapItems, hasIdMap map[int]string) (returnSlice []*models.CygxIndustryMapItems, ok bool) {
	if depth != 0 {
		returnSlice = tmpReturnSlice
	}
	depth++
	returnSlice = append(returnSlice, rootNode)
	//if _,ok := hasIdMap[rootNode.IndustryMapId];ok==false{
	//	hasIdMap[rootNode.IndustryMapId] = ""
	//}
	if rootNode.Children != nil {
		for _, v := range rootNode.Children {
			if v.ParentId == nowNode.ParentId {
				ok = true
				return
			}
			returnSlice, ok = parentTreeToSlice(v, nowNode, depth, returnSlice, hasIdMap)
			//如果返回的匹配完成，那么不进入下一次循环，直接返回
			if ok {
				return
			}

			//一次循环结束后，如果没有匹配上，那么移除临时切片中的数据
			returnSlice = append(returnSlice[:0], returnSlice[0:depth]...)
		}
	}

	return
}

//切片乱序
func randSlice(slice []*models.CygxIndustryMapItems) {
	rv := reflect.ValueOf(slice)
	if rv.Type().Kind() != reflect.Slice {
		return
	}

	length := rv.Len()
	if length < 2 {
		return
	}

	swap := reflect.Swapper(slice)
	rand.Seed(time.Now().Unix())
	for i := length - 1; i >= 0; i-- {
		j := rand.Intn(length)
		swap(i, j)
	}
	return
}

//获取行业图谱切片（v2版本，调整时间：2021-03-19 18:02:07）
func GetIndustryMapNameSliceV2(industryName string) (nameSlice []string, err error) {
	nameSlice = append(nameSlice, industryName)
	tree, err := GetIndustryTree()
	if err != nil {
		fmt.Println("获取树失败")
		return
	}

	//fmt.Println(tree)

	//已经存在的行业id的map集合
	hasIdMap := make(map[int]string)
	itemList, err := models.GetFirstCygxIndustryListByName(industryName)
	if err != nil {
		fmt.Println("获取数据失败,", err)
		return
	}
	//找不到对应的数据
	if len(itemList) <= 0 {
		return
	}

	industryMapList := make(map[int][]*models.CygxIndustryMapItems)
	//TODO  这里好像有问题，如果传入行业的话，上面再没有是否只是找到第一个节点判断，那么就会异常抛出
	for _, item := range itemList {
		industryMapList[item.Level] = append(industryMapList[item.Level], item)
	}

	//将查出来的根节点数据的key取出来，放在切片中，并对该切片做正序排列
	var sortIndustryList []int
	for k, _ := range industryMapList {
		sortIndustryList = append(sortIndustryList, k)
	}
	sort.Ints(sortIndustryList)

	//最底层节点的数据集合
	list := industryMapList[sortIndustryList[0]]

	//如果该数据正好是第一层节点数据，那么需要额外判断下
	if list[0].ParentId <= 2 {
		//如果存在第二级，那么就使用该层级
		if len(sortIndustryList) > 1 {
			list = industryMapList[sortIndustryList[1]]
		}
	}
	//fmt.Println(list)
	//return

	otherChildMapSlice := map[int][]*models.CygxIndustryMapItems{}

	//多个节点时，额外处理
	if len(list) > 1 {
		for _, item := range list {
			hasIdMap[item.IndustryMapId] = ""
			//将自己的节点给加进去
			otherChildMapSlice[0] = append(otherChildMapSlice[0], item)

			//获取上级
			var tmpParentSlice []*models.CygxIndustryMapItems
			tmpParentSlice, _ = parentTreeToSlice(tree, item, 0, tmpParentSlice, hasIdMap)
			//父节点
			parentItem := tmpParentSlice[len(tmpParentSlice)-1]
			if _, ok := hasIdMap[parentItem.IndustryMapId]; ok == false {
				hasIdMap[parentItem.IndustryMapId] = ""
				otherChildMapSlice[1] = append(otherChildMapSlice[1], parentItem)
			}
		}
	} else {
		//匹配到单个节点
		item := list[0]
		hasIdMap[item.IndustryMapId] = ""
		//将自己的节点给加进去
		otherChildMapSlice[0] = append(otherChildMapSlice[0], item)
		childTree := getChildTree(tree, item)

		//如果是命中到最后一层节点
		if len(childTree.Children) == 0 {
			//获取上级
			var tmpParentSlice []*models.CygxIndustryMapItems
			tmpParentSlice, _ = parentTreeToSlice(tree, item, 0, tmpParentSlice, hasIdMap)
			//父节点
			parentItem := tmpParentSlice[len(tmpParentSlice)-1]

			if _, ok := hasIdMap[parentItem.IndustryMapId]; ok == false {
				hasIdMap[parentItem.IndustryMapId] = ""
				otherChildMapSlice[1] = append(otherChildMapSlice[1], parentItem)
			}

			//兄弟节点
			siblingTreeToSliceV2(parentItem, item, hasIdMap, 2, otherChildMapSlice)
		} else {
			//如果不是命中到最后一层节点
			otherChildMapSlice[1] = append(otherChildMapSlice[1], childTree.Children...)
		}
	}

	//return
	var tmpSlice []*models.CygxIndustryMapItems

	//将其他规律数据的key取出来，放在切片中，并对该切片做正序排列
	var sortList []int
	for k, _ := range otherChildMapSlice {
		sortList = append(sortList, k)
	}
	sort.Ints(sortList)

	//遍历该切片，根据下标key获取对应的数据，并插入到主数据中
	for _, v := range sortList {
		tmpChildSlice := otherChildMapSlice[v]
		randSlice(tmpChildSlice)
		tmpSlice = append(tmpSlice, tmpChildSlice...)
		//fmt.Println(k,"=====")
		//for _,tmpV := range otherChildMapSlice[v]{
		//	fmt.Println(tmpV.IndustryMapName)
		//}
	}
	//名字切片
	for _, v := range tmpSlice {
		//fmt.Println("k===",k,"=======v=======",v)
		nameSlice = append(nameSlice, v.IndustryMapName)
	}

	//fmt.Println(nameSlice)
	//fmt.Println(strings.Join(nameSlice,","))
	//utils.FileLog.Info("allNodes:%s",strings.Join(nameSlice,","))
	return
}

//获取行业图谱切片（v3版本，调整时间：2021-04-20 17:23:31，不乱序）
func GetIndustryMapNameSliceV3(industryName string) (nameSlice []string, err error) {
	nameSlice = append(nameSlice, industryName)
	tree, err := GetIndustryTree()
	if err != nil {
		fmt.Println("获取树失败")
		return
	}

	//fmt.Println(tree)

	//已经存在的行业id的map集合
	hasIdMap := make(map[int]string)
	itemList, err := models.GetFirstCygxIndustryListByName(industryName)
	if err != nil {
		fmt.Println("获取数据失败,", err)
		return
	}
	//找不到对应的数据
	if len(itemList) <= 0 {
		return
	}

	industryMapList := make(map[int][]*models.CygxIndustryMapItems)
	//TODO  这里好像有问题，如果传入行业的话，上面再没有是否只是找到第一个节点判断，那么就会异常抛出
	for _, item := range itemList {
		industryMapList[item.Level] = append(industryMapList[item.Level], item)
	}

	//将查出来的根节点数据的key取出来，放在切片中，并对该切片做正序排列
	var sortIndustryList []int
	for k, _ := range industryMapList {
		sortIndustryList = append(sortIndustryList, k)
	}
	sort.Ints(sortIndustryList)

	//最底层节点的数据集合
	list := industryMapList[sortIndustryList[0]]

	//如果该数据正好是第一层节点数据，那么需要额外判断下
	if list[0].ParentId <= 2 {
		//如果存在第二级，那么就使用该层级
		if len(sortIndustryList) > 1 {
			list = industryMapList[sortIndustryList[1]]
		}
	}
	//fmt.Println(list)
	//return

	otherChildMapSlice := map[int][]*models.CygxIndustryMapItems{}

	//多个节点时，额外处理
	if len(list) > 1 {
		for _, item := range list {
			hasIdMap[item.IndustryMapId] = ""
			//将自己的节点给加进去
			otherChildMapSlice[0] = append(otherChildMapSlice[0], item)

			//获取上级
			var tmpParentSlice []*models.CygxIndustryMapItems
			tmpParentSlice, _ = parentTreeToSlice(tree, item, 0, tmpParentSlice, hasIdMap)
			//父节点
			parentItem := tmpParentSlice[len(tmpParentSlice)-1]
			if _, ok := hasIdMap[parentItem.IndustryMapId]; ok == false {
				hasIdMap[parentItem.IndustryMapId] = ""
				otherChildMapSlice[1] = append(otherChildMapSlice[1], parentItem)
			}
		}
	} else {
		//匹配到单个节点
		item := list[0]
		hasIdMap[item.IndustryMapId] = ""
		//将自己的节点给加进去
		otherChildMapSlice[0] = append(otherChildMapSlice[0], item)
		childTree := getChildTree(tree, item)

		//如果是命中到最后一层节点
		if len(childTree.Children) == 0 {
			//获取上级
			var tmpParentSlice []*models.CygxIndustryMapItems
			tmpParentSlice, _ = parentTreeToSlice(tree, item, 0, tmpParentSlice, hasIdMap)
			//父节点
			parentItem := tmpParentSlice[len(tmpParentSlice)-1]

			if _, ok := hasIdMap[parentItem.IndustryMapId]; ok == false {
				hasIdMap[parentItem.IndustryMapId] = ""
				otherChildMapSlice[1] = append(otherChildMapSlice[1], parentItem)
			}

			//兄弟节点
			siblingTreeToSliceV2(parentItem, item, hasIdMap, 2, otherChildMapSlice)
		} else {
			//如果不是命中到最后一层节点
			otherChildMapSlice[1] = append(otherChildMapSlice[1], childTree.Children...)
		}
	}

	//return
	var tmpSlice []*models.CygxIndustryMapItems

	//将其他规律数据的key取出来，放在切片中，并对该切片做正序排列
	var sortList []int
	for k, _ := range otherChildMapSlice {
		sortList = append(sortList, k)
	}
	sort.Ints(sortList)

	//遍历该切片，根据下标key获取对应的数据，并插入到主数据中
	for _, v := range sortList {
		tmpChildSlice := otherChildMapSlice[v]
		//randSlice(tmpChildSlice)
		tmpSlice = append(tmpSlice, tmpChildSlice...)
		//fmt.Println(k,"=====")
		//for _,tmpV := range otherChildMapSlice[v]{
		//	fmt.Println(tmpV.IndustryMapName)
		//}
	}
	//名字切片
	for _, v := range tmpSlice {
		//fmt.Println("k===",k,"=======v=======",v)
		nameSlice = append(nameSlice, v.IndustryMapName)
	}

	//fmt.Println(nameSlice)
	//fmt.Println(strings.Join(nameSlice,","))
	//utils.FileLog.Info("allNodes:%s",strings.Join(nameSlice,","))
	return
}

//获取兄弟级树
func siblingTreeToSliceV2(rootNode *models.CygxIndustryMapItems, nowNode *models.CygxIndustryMapItems, hasIdMap map[int]string, depth int, otherChildMapSlice map[int][]*models.CygxIndustryMapItems) (maxDepth int) {
	if rootNode.Children != nil {
		depth++
		maxDepth = depth
		for _, v := range rootNode.Children {
			//如果父级id一致的情况下，那么代表这是兄弟节点或者是自己了
			if v.ParentId == nowNode.ParentId {
				//判断是否已经录入，如果已经录入，那么不处理
				if _, ok := hasIdMap[v.IndustryMapId]; ok == false {
					otherChildMapSlice[depth] = append(otherChildMapSlice[depth], v)
					hasIdMap[v.IndustryMapId] = ""
				}
			} else {
				returnDepth := siblingTreeToSliceV2(v, nowNode, hasIdMap, depth, otherChildMapSlice)
				if returnDepth > maxDepth {
					maxDepth = returnDepth
				}
			}
		}
	}
	return
}

//region数据修复
func FixData() {
	tree, err := GetIndustryTree()
	if err != nil {
	}
	models.FixLevelData(tree.IndustryMapId, 1)
	fixData(tree, 1)
	return
}

func fixData(item *models.CygxIndustryMapItems, depth int) {
	depth++
	if item.Children == nil {
		return
	}
	for _, v := range item.Children {
		models.FixLevelData(v.IndustryMapId, depth)
		fixData(v, depth)
	}
}

//endregion
