package corntask

import (
	"cluster"
	"config"
	"gopkg.in/mgo.v2/bson"
	"log"
	"math"
	mu "mfw/util"
	"net"
	"qfw/util"
	"qfw/util/mongodb"
	"time"
)

var Auto = func() {
	d := time.Now()
	if config.Isjjr{
		log.Println(d.Format("20060102"),"节假日")
		return
	}
	nowday := time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location())
	cluster.DescribeInstances() //查询多台实例的详细信息
	tnum:=0
	cluster.CID.Range(func(key, value interface{}) bool {
		tnum +=1
		return true
	})
	log.Println("实例数量：",tnum)
	ocrescs := mongodb.Find("ocr_ecs", bson.M{}, nil, bson.M{"AutoReleaseTime": 1}, false, -1, -1)
	if ocrescs != nil || len(*ocrescs) > 0 {
		for _, v := range (*ocrescs) {
			if util.ObjToString(v["AutoReleaseTime"]) != "" {
				utc, err := time.ParseInLocation("2006-01-02T15:04Z", util.ObjToString(v["AutoReleaseTime"]), time.Local)
				if err != nil {
					log.Println("解析时间异常", err)
					continue
				}
				if utc.Before(nowday) {
					log.Println("删除过时实例", mongodb.Del("ocr_ecs", bson.M{"_id": v["_id"].(bson.ObjectId)}))
				}
			}
		}
	}
	taskArr := mongodb.Find("ocr_task", bson.M{"isrun":bson.M{
		"$ne":"stop",
	}}, `{_id:1}`, nil, false, -1, -1)
	taskNum := len(*taskArr)
	log.Println("当前任务数量：", taskNum)
	//if taskNum <= 0 {
	//计算释放,发送udp
	ccnum := compute()
	log.Println("ccnum:", ccnum, ", len(config.CID):", tnum, cluster.CID)
	escObject := mongodb.Find("ocr_ecs", bson.M{"TaskName": "ocr_task_arr", "OcrTaskStatus": "none"}, bson.M{"_id": -1}, nil, false, -1, -1)
	log.Println("实例未部署数量", len(*escObject))
	//释放实例
	if ccnum <= 0 {
		if tnum == 0 {
			log.Println("当前实例为空,无需释放", cluster.CID, )
			return
		}
		zsa := time.Date(d.Year(), d.Month(), d.Day(), util.IntAll(config.Sysconfig["swa"]), 0, 0, 0, d.Location())
		zsb := time.Date(d.Year(), d.Month(), d.Day(), util.IntAll(config.Sysconfig["swb"]), 0, 0, 0, d.Location())

		xwa := time.Date(d.Year(), d.Month(), d.Day(), util.IntAll(config.Sysconfig["xwa"]), 0, 0, 0, d.Location())
		xwb := time.Date(d.Year(), d.Month(), d.Day(), util.IntAll(config.Sysconfig["xwb"]), 0, 0, 0, d.Location())
		if !((zsa.Before(d) && zsb.After(d)) || (xwa.Before(d) && xwb.After(d))){
			if ccnum == 0 && tnum > 0 {
				log.Println("释放所有实例", cluster.CID)
				cluster.CID.Range(func(tmpIid, value interface{}) bool {
					ttt := mongodb.FindOne("ocr_ecs", bson.M{"InstanceId": tmpIid})
					log.Println("5分钟后释放实例", tmpIid)
					go func(tmpIid string,ttt *map[string]interface{}) {
						time.Sleep(time.Minute * 5)
						config.Udpclient.WriteUdp([]byte("5分钟后释放实例"), mu.OP_DELETE_DOWNLOADERCODES, &net.UDPAddr{
							IP:   net.ParseIP(util.ObjToString((*ttt)["ip_nw"])),
							Port: util.IntAll(config.Sysconfig["broadcast_port"]),
						})
						mongodb.Del("ocr_ecs", bson.M{"InstanceId": tmpIid})
						cluster.DeleteInstance(tmpIid)
						cluster.CID.Delete(tmpIid)
						log.Println("5分钟后释放实例完成", tmpIid)
					}(util.ObjToString(tmpIid),ttt)
					return true
				})
				//for tmpIid, _ := range cluster.CID {
				//	ttt := mongodb.FindOne("ocr_ecs", bson.M{"InstanceId": tmpIid})
				//	log.Println("5分钟后释放实例", tmpIid)
				//	go func(tmpIid string,ttt *map[string]interface{}) {
				//		time.Sleep(time.Minute * 5)
				//		config.Udpclient.WriteUdp([]byte("5分钟后释放实例"), mu.OP_DELETE_DOWNLOADERCODES, &net.UDPAddr{
				//			IP:   net.ParseIP(util.ObjToString((*ttt)["ip_nw"])),
				//			Port: util.IntAll(config.Sysconfig["broadcast_port"]),
				//		})
				//		mongodb.Del("ocr_ecs", bson.M{"InstanceId": tmpIid})
				//		cluster.DeleteInstance(tmpIid)
				//		log.Println("5分钟后释放实例完成", tmpIid)
				//	}(tmpIid,ttt)
				//}
			} else {
				var tmpnum int
				//for k, _ := range cluster.CID {
				//	if ccnum >= tmpnum {
				//		return
				//	}
				//	tmpIid := k
				//	ttt := mongodb.FindOne("ocr_ecs", bson.M{"InstanceId": tmpIid})
				//	log.Println("5分钟后释放实例", tmpIid)
				//	go func(tmpIid string,ttt *map[string]interface{}) {
				//		time.Sleep(time.Minute * 5)
				//		config.Udpclient.WriteUdp([]byte("5分钟后释放实例"), mu.OP_DELETE_DOWNLOADERCODES, &net.UDPAddr{
				//			IP:   net.ParseIP(util.ObjToString((*ttt)["ip_nw"])),
				//			Port: util.IntAll(config.Sysconfig["broadcast_port"]),
				//		})
				//		mongodb.Del("ocr_ecs", bson.M{"InstanceId": tmpIid})
				//		cluster.DeleteInstance(tmpIid)
				//		log.Println("5分钟后释放实例完成", tmpIid)
				//	}(tmpIid,ttt)
				//	tmpnum--
				//}
				cluster.CID.Range(func(k, value interface{}) bool {
					if ccnum >= tmpnum {
						return false
					}
					tmpIid := util.ObjToString(k)
					ttt := mongodb.FindOne("ocr_ecs", bson.M{"InstanceId": tmpIid})
					log.Println("5分钟后释放实例", tmpIid)
					go func(tmpIid string,ttt *map[string]interface{}) {
						time.Sleep(time.Minute * 5)
						config.Udpclient.WriteUdp([]byte("5分钟后释放实例"), mu.OP_DELETE_DOWNLOADERCODES, &net.UDPAddr{
							IP:   net.ParseIP(util.ObjToString((*ttt)["ip_nw"])),
							Port: util.IntAll(config.Sysconfig["broadcast_port"]),
						})
						mongodb.Del("ocr_ecs", bson.M{"InstanceId": tmpIid})
						cluster.DeleteInstance(tmpIid)
						cluster.CID.Delete(tmpIid)
						log.Println("5分钟后释放实例完成", tmpIid)
					}(tmpIid,ttt)
					tmpnum--
					return true
				})
			}
		}
		cluster.DescribeInstances()
		escObject := mongodb.Find("ocr_ecs", bson.M{"TaskName": "ocr_task_arr", "OcrTaskStatus": "none"}, bson.M{"_id": -1}, nil, false, -1, -1)
		log.Println("实例未部署数量", len(*escObject))
		if escObject != nil || len(*escObject) > 0 {
			for i, v := range (*escObject) {
				if tmpip := util.ObjToString(v["ip_nw"]); tmpip == "" {
					log.Println("没用获取到ip,实例ip异常", tmpip)
				} else {
					go func(tmpip, InstanceId string, i int) {
						if DoCMD(tmpip) {
							var tmpstr string
							isok2, udpstr := cluster.SshPgrep(tmpip, "pgrep udp2019")
							tmpstr += udpstr + ";&nbsp;&nbsp;"
							isok3, fil2textstr := cluster.SshPgrep(tmpip, "pgrep file2text")
							tmpstr += fil2textstr
							if isok2 && isok3 {
								(*escObject)[i]["OcrTaskStatus"] = "successful"
								mongodb.Update("ocr_ecs", bson.M{"_id": (*escObject)[i]["_id"]}, (*escObject)[i], true, false)
								log.Println((*escObject)[i]["_id"], tmpip, "部署成功")
							} else {
								log.Println(tmpip, "部署异常,"+tmpstr)
							}
						} else {
							log.Println(tmpip, "部署失败")
						}
					}(tmpip, util.ObjToString(v["InstanceId"]), i)
				}
			}
		}
		return
	}
	//}
	//重新部署未完成实例
	log.Println("tnum >= util.IntAll(config.Sysconfig[pernum])",tnum ,util.IntAll(config.Sysconfig["pernum"]))
	if tnum >= util.IntAll(config.Sysconfig["pernum"]) {
		log.Println("实例申请上限,当前实例:", cluster.CID)
		log.Println("实例未部署数量", len(*escObject))
		if escObject != nil || len(*escObject) > 0 {
			for i, v := range (*escObject) {
				if tmpip := util.ObjToString(v["ip_nw"]); tmpip == "" {
					log.Println("没用获取到ip,实例ip异常", tmpip)
				} else {
					go func(tmpip, InstanceId string, i int) {
						if DoCMD(tmpip) {
							var tmpstr string
							isok2, udpstr := cluster.SshPgrep(tmpip, "pgrep udp2019")
							tmpstr += udpstr + ";&nbsp;&nbsp;"
							isok3, fil2textstr := cluster.SshPgrep(tmpip, "pgrep file2text")
							tmpstr += fil2textstr
							if isok2 && isok3 {
								(*escObject)[i]["OcrTaskStatus"] = "successful"
								mongodb.Update("ocr_ecs", bson.M{"_id": (*escObject)[i]["_id"]}, (*escObject)[i], true, false)
								log.Println((*escObject)[i]["_id"], tmpip, "部署成功")
							} else {
								log.Println(tmpip, "部署异常,"+tmpstr)
							}
						} else {
							log.Println(tmpip, "部署失败")
						}
					}(tmpip, util.ObjToString(v["InstanceId"]), i)
				}
			}
		}
		return
	}
	//if taskNum > 1 {
	//申请实例
	log.Println("申请实例")
	now := time.Now()
	hours := time.Date(now.Year(), now.Month(), now.Day(), 20, 0, 0, 0, now.Location()).Sub(now).Hours()
	cluster.RunInstances("ocr_task_arr", "8", "false", ccnum, int(math.Round(hours)))
	log.Println("实例申请成功")
	DynamicTask() //动态任务
	log.Println("申请实例结束")
	//}
}

func DoCMD(ip string) bool {
	if ip == "" {
		return false
	}

	return cluster.RunSsh(ip)
}
func DynamicTask() {
	time.Sleep(time.Second * 35)
	cluster.DescribeInstances() //查询多台实例的详细信息
	escObject := mongodb.Find("ocr_ecs", bson.M{"TaskName": "ocr_task_arr", "OcrTaskStatus": "none"}, bson.M{"_id": -1}, nil, false, -1, -1)
	log.Println("实例未部署数量", len(*escObject))
	if escObject != nil || len(*escObject) > 0 {
		for i, v := range (*escObject) {
			if tmpip := util.ObjToString(v["ip_nw"]); tmpip == "" {
				log.Println("没用获取到ip,实例ip异常", tmpip)
				DynamicTask()
				return
			} else {
				go func(tmpip, InstanceId string, i int) {
					if DoCMD(tmpip) {
						var tmpstr string
						isok2, udpstr := cluster.SshPgrep(tmpip, "pgrep udp2019")
						tmpstr += udpstr + ";&nbsp;&nbsp;"
						isok3, fil2textstr := cluster.SshPgrep(tmpip, "pgrep file2text")
						tmpstr += fil2textstr
						if isok2 && isok3 {
							(*escObject)[i]["OcrTaskStatus"] = "successful"
							mongodb.Update("ocr_ecs", bson.M{"_id": (*escObject)[i]["_id"]}, (*escObject)[i], true, false)
							//config.Sys.Lock()
							//if cluster.CID[InstanceId] == "" && InstanceId != "" {
							//	cluster.CID[InstanceId] = tmpip
							//}
							if cv,ok :=cluster.CID.Load(InstanceId);ok && cv =="" &&InstanceId != ""{
									cluster.CID.Store(InstanceId, tmpip)
							}
							//config.Sys.Unlock()
							log.Println((*escObject)[i]["_id"], tmpip, "部署成功")
						} else {
							log.Println(tmpip, "部署异常,"+tmpstr)
						}
					} else {
						log.Println(tmpip, "部署失败")
					}
				}(tmpip, util.ObjToString(v["InstanceId"]), i)
			}
		}
	} else {
		log.Println("动态任务创建失败")
	}
}
func compute() int {
	nowtime := time.Now().Unix()
	taskArrase := mongodb.Find("ocr_task", bson.M{"isrun":bson.M{
		"$ne":"stop",
	}}, `{_id:1}`, nil, false, -1, -1)
	if taskArrase == nil || len(*taskArrase) == 0 {
		log.Println(464, "nil ro len(*taskArrase) == 0")
		return 0
	}
	stmp := (*taskArrase)[0]
	etmp := (*taskArrase)[len(*taskArrase)-1]
	if stmp != nil && etmp != nil {
		stime := util.Int64All(stmp["import_time"])
		if nowtime-stime <= util.Int64All(config.Sysconfig["time_consuming_limit"]) {
			log.Println(472, nowtime-stime, "<=", util.Int64All(config.Sysconfig["time_consuming_limit"]))
			return 0
		}

		sid := bson.ObjectIdHex(util.ObjToString(stmp["start"]))
		eid := bson.ObjectIdHex(util.ObjToString(etmp[util.ObjToString(config.EidField)]))
		sum := mongodb.Count("bidding", bson.M{"_id": bson.M{
			"$gte": sid,
			"$lt":  eid,
		}})
		if sum <= util.IntAll(config.Sysconfig["accumulated_task_limit"]) {
			log.Println(483, sum, sid, eid)
			return 0
		}
		gteid := bson.ObjectIdHex(util.ObjToString(stmp[util.ObjToString(config.SidField)]))
		overNum := mongodb.Count("bidding", bson.M{"_id": bson.M{
			"$gte": sid,
			"$lt":  gteid,
		}})
		if overNum == 0 {
			log.Println(492, overNum, sid, gteid)
			return 0
		}
		if sum <= util.IntAll(config.Sysconfig["accumulated_task_lowlimit"]) {
			log.Println(496, sum, "<=", util.IntAll(config.Sysconfig["accumulated_task_lowlimit"]))
			return 0
		}
		tnum :=mongodb.Count("ocr_ecs",bson.M{"OcrTaskStatus":"successful"})
		mtmm := float64(overNum) / float64(nowtime-stime) / float64(tnum+util.IntAll(config.Sysconfig["gdts"])) //每台每秒
		if mtmm <= 0 {
			log.Println(501, overNum, int(nowtime-stime), (tnum + util.IntAll(config.Sysconfig["gdts"])))
			return 0
		}
		cc := float64(sum)/float64(util.IntAll(config.Sysconfig["corntime_consuming"]))/mtmm - float64(tnum) - float64(util.IntAll(config.Sysconfig["gdts"]))
		log.Println("overNum:", overNum, ",hs:", int(nowtime-stime), ",mtms:", mtmm, ",sum:", sum, cc)
		if cc > util.Float64All(config.Sysconfig["pernum"]) {
			return util.IntAll(config.Sysconfig["pernum"])
		} else {
			return int(cc)
		}
	}
	return 0
}
