package web

import (
	"encoding/json"
	"jy/cluster"
	"net"
	"time"

	"log"
	mu "mfw/util"
	"net/http"
	qu "qfw/util"
	. "tools"
	u "util"

	"go.mongodb.org/mongo-driver/bson/primitive"
)

//按小时id划段
func IdsRange(table, sdate, edate string) int {
	start, _ := time.ParseInLocation(qu.Date_Short_Layout, sdate, time.Local)
	end, _ := time.ParseInLocation(qu.Date_Short_Layout, edate, time.Local)
	nums := 0
	for start.Unix() <= end.Unix() {
		nums++
		timestr := start.Format("2006-01-02 15:04:05")
		sid := primitive.NewObjectIDFromTimestamp(start)
		start = start.Add(24 * time.Hour)
		eid := primitive.NewObjectIDFromTimestamp(start)
		MgoDcs.Save("esctask", map[string]interface{}{
			"timestr": timestr,
			"sid":     u.BsonIdToSId(sid),
			"eid":     u.BsonIdToSId(eid),
			"state":   0, //0待执行，1执行中，2完成
		})
	}
	return nums
}

//启动任务
func RunEcsTask() int {
	list, _ := MgoDcs.Find("ecs", `{"extstatus":"deploy"}`, nil, nil, false, -1, -1)
	num := 0
	for _, v := range *list {
		ip := qu.ObjToString(v["ip_nw"])
		by, _ := json.Marshal(map[string]interface{}{
			"ip":         ip,
			"InstanceId": v["InstanceId"],
			"stype":      "distributed",
		})

		log.Println("执行--", v["InstanceId"], net.ParseIP(ip), qu.IntAll(Config["udpport"]))

		err := Udpclient.WriteUdp(by, mu.OP_TYPE_DATA, &net.UDPAddr{
			IP:   net.ParseIP(ip),
			Port: qu.IntAll(Config["udpport"]),
		})

		if err != nil {
			log.Println(err)
		} else {
			num++
			time.Sleep(2 * time.Second)
			log.Println("分发任务", string(by))
		}
	}
	return num
}

func distributed(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	if CheckSession(w, r) {
		ss, _ := Store.Get(r, SN)
		data := map[string]interface{}{"s_name": ss.Values["s_name"]}
		//查询配置规则
		//MgoDcs.DbName = "extract_kf"
		res, _ := MgoDcs.Find("ecs", `{}`, `{"_id":-1}`, nil, false, -1, -1)
		data["data"] = res
		ExecuteTpl("distributed.html", &data, w)
	} else {
		http.Redirect(w, r, "/", http.StatusFound)
	}

}

//部署
func deployOneInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		log.Println(r)
		InstanceId := r.FormValue("_id")
		if InstanceId == "" {
			res.Msg = "id不能为空"
		} else {
			tmp, b := MgoDcs.FindOneByField("ecs", `{"InstanceId":"`+InstanceId+`"}`, `{"ip_nw":1,"InstanceId":1}`)
			if b && tmp != nil {
				ip := qu.ObjToString((*tmp)["ip_nw"])
				id := qu.ObjToString((*tmp)["InstanceId"])
				MgoDcs.Update("ecs", `{"ip_nw":"`+ip+`"}`,
					map[string]interface{}{
						"$set": map[string]interface{}{
							"extstatus": "",
						},
					}, true, false)
				log.Println("部署", "ip--", ip, "id--", id)

				cluster.RunSsh(ip, cluster.Password, 22)

				MgoDcs.Update("ecs", `{"ip_nw":"`+ip+`"}`,
					map[string]interface{}{
						"$set": map[string]interface{}{
							"extstatus": "deploy",
						},
					}, true, false)
				res.Status = true
				res.Msg = "部署成功"
			} else {
				res.Msg = "没查到id"
			}

		}
	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//执行
func executeOneInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		log.Println(r)
		InstanceId := r.FormValue("_id")
		if InstanceId == "" {
			res.Msg = "id不能为空"
		} else {
			tmp, b := MgoDcs.FindOneByField("ecs", `{"InstanceId":"`+InstanceId+`"}`, `{"ip_nw":1,"lastId":1,"extask":1}`)
			if b && tmp != nil {
				ip := ""
				ip = qu.ObjToString((*tmp)["ip_nw"])
				by, _ := json.Marshal(map[string]interface{}{
					"ip":         ip,
					"InstanceId": InstanceId,
					"stype":      "distributed",
				})
				log.Println("执行--", InstanceId, ip, net.ParseIP(ip), qu.IntAll(Config["udpport"]))
				err := Udpclient.WriteUdp(by, mu.OP_TYPE_DATA, &net.UDPAddr{
					IP:   net.ParseIP(ip),
					Port: qu.IntAll(Config["udpport"]),
				})

				if err != nil {
					log.Println(err)
					log.Println("udp失败")
					res.Msg = "执行失败--"
				} else {
					log.Println("udp成功")
					res.Status = true
					res.Msg = "执行成功--"
				}
			} else {
				res.Msg = "没查到id"
			}
		}
	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//释放
func releaseOneInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		log.Println(r)
		InstanceId := r.FormValue("_id")
		if InstanceId == "" {
			res.Msg = "id不能为空"
		} else {
			cluster.DeleteInstance(InstanceId)
			res.Status = true
			res.Msg = "释放成功"
		}
	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//删除
func deleteOneInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		log.Println(r)
		InstanceId := r.FormValue("_id")
		if InstanceId == "" {
			res.Msg = "id不能为空"
		} else {
			b := MgoDcs.Del("ecs", `{"InstanceId":"`+InstanceId+`"}`)
			if b {
				res.Status = true
				res.Msg = "删除成功"
			} else {
				res.Msg = "删除失败"
			}
		}

	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//申请ecs实例
func applyInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		TaskName := r.FormValue("s_name")
		s_computer := r.FormValue("s_computer")
		s_flow := r.FormValue("s_flow")
		num := r.FormValue("i_num")
		hours := r.FormValue("i_hours")
		log.Println(TaskName, s_computer, s_flow, num, hours)
		cluster.RunInstances(TaskName, s_computer, s_flow, qu.IntAll(num), qu.IntAll(hours))
		res.Msg = "申请实例..."
		res.Status = true
	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//更新实例状态
func updateInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		cluster.DescribeInstances()
		res.Msg = "更新实力状态..."
		res.Status = true
	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//id划段 生成任务
func createTask(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		s_table := r.FormValue("s_table")
		sdate := r.FormValue("s_date")
		edate := r.FormValue("e_date")
		log.Println(s_table, sdate, edate)
		res.Msg = "id段..."
		res.Status = true
		IdsRange(s_table, sdate, edate)
	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//部署任务
func deployAllInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		list, _ := MgoDcs.Find("ecs", `{"Status":"Running"}`, nil, nil, false, -1, -1)
		ch := make(chan bool, 5)
		for _, v := range *list {
			time.Sleep(1 * time.Second)
			ch <- true
			go func(v map[string]interface{}) {
				ip := qu.ObjToString(v["ip_nw"])
				id := qu.ObjToString(v["InstanceId"])
				log.Println("部署", ip, id)

				cluster.RunSsh(ip, cluster.Password, 22)
				MgoDcs.Update("ecs", `{"ip_nw":"`+ip+`"}`,
					map[string]interface{}{
						"$set": map[string]interface{}{
							"extstatus": "deploy",
						},
					}, true, false)
				<-ch
			}(v)
		}

		if len(*list) > 0 {
			res.Msg = "部署成功..."
			res.Status = true
		} else {
			res.Msg = "部署失败..."
			res.Status = true
		}

	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//执行任务
func executeAllInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		num := RunEcsTask()
		log.Println("任务分发完成", num)
		res.Status = true
		res.Msg = "任务执行"
	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}

//实例自动释放
func settingInstance(w http.ResponseWriter, r *http.Request) {
	defer Catch()
	res := JSON{}
	if CheckSession(w, r) {
		instanceid := r.FormValue("instanceid")
		hours := r.FormValue("hours")
		hour := qu.IntAll(hours)
		log.Println(instanceid, hour)
		if hour > 0 {
			cluster.ModifyInstanceAutoReleaseTime(instanceid, hour)
		}
	} else {
		res.Msg = "重新登陆"
	}
	WriteJSON(w, &res)
}
