package pods

import (
	"bufio"
	"github.com/astaxie/beego"
	"github.com/gorilla/websocket"
	"k8s-console/utils"
	"k8s.io/api/core/v1"
	"net/http"
	"strings"
	"time"
)

type TailPodLogController struct {
	beego.Controller
}

//URLMapping ...
func (c *TailPodLogController) URLMapping() {
	c.Mapping("tailPodLog", c.TailPodLog)
}

var (
	upgrade = websocket.Upgrader{
		// 跨域
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
	webSocketClientMap = map[string]*websocket.Conn{}
)

// get ...
// @Title TailPodLog
// @Description tail podLog
// @Param	nameSpace		query 	string	true	"nameSpace"
// @Param	podName		query 	string	true	"pod name"
// @Param	container		query 	string	true	"container name in pod"
// @router /tailPodLog [get]
func (c *TailPodLogController) TailPodLog() {
	ws, err := upgrade.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
	if err != nil {
		errorLogger.Println(err.Error())
		return
	}
	defer ws.Close()

	clientAddr := ws.RemoteAddr().String()
	infoLogger.Println("获取容器日志ws客户端地址:", clientAddr)

	//校验license是否失效
	//verifyLicenseValidRes := controllers.VerifyLicenseValid("zh")
	//logs.GetLogger("info").Println(verifyLicenseValidRes)
	//if verifyLicenseValidRes.Status == 300 {
	//	logs.GetLogger("error").Printf("校验license是否失效: %s", verifyLicenseValidRes.Message)
	//	ws.WriteJSON(verifyLicenseValidRes.Message)
	//	return
	//}

	//保存ws连接
	webSocketClientMap[clientAddr] = ws

	nameSpace := c.GetString("nameSpace")
	podName := c.GetString("podName")
	container := c.GetString("container")

	infoLogger.Printf("获取容器日志请求参数: %s, %s, %s", nameSpace, podName, container)
	infoLogger.Printf("当前ws客户端连接个数: %d", len(webSocketClientMap))

	defer func() {
		if err := recover(); err != nil {
			errorLogger.Println("捕获错误信息: ", err)
		}
	}()

	if strings.TrimSpace(podName) == "" || strings.TrimSpace(podName) == "undefined" {
		errorLogger.Printf("pod名称: %s无效", podName)
		webSocketClientMap[clientAddr].WriteJSON(utils.GetI18nLang("en", "createK8sConFail"))
		webSocketClientMap[clientAddr].Close()
		delete(webSocketClientMap, clientAddr)
		return
	}
	if strings.TrimSpace(container) == "" {
		errorLogger.Printf("容器名称: %s无效", container)
		webSocketClientMap[clientAddr].WriteJSON(utils.GetI18nLang("en", "createK8sConFail"))
		webSocketClientMap[clientAddr].Close()
		delete(webSocketClientMap, clientAddr)
		return
	}

	// 获取k8s客户端
	k8sClient := utils.GetK8sClient()
	if k8sClient == nil {
		infoLogger.Println(utils.GetI18nLang("en", "createK8sConFail"))
		if _, ok := webSocketClientMap[clientAddr]; ok {
			webSocketClientMap[clientAddr].WriteJSON(utils.GetI18nLang("en", "createK8sConFail"))
			webSocketClientMap[clientAddr].Close()
			delete(webSocketClientMap, clientAddr)
		}
		return
	}

	//查询集群所有命名空间信息
	allNameSpaceList, err := utils.GetClusterAllNameSpaces("zh")
	infoLogger.Println(allNameSpaceList)
	if err != nil {
		errorLogger.Printf("查询集群所有命名空间失败: %s", err.Error())
		webSocketClientMap[clientAddr].WriteJSON(utils.GetI18nLang("en", "getClusterAllNamespacesFail"))
		webSocketClientMap[clientAddr].Close()
		delete(webSocketClientMap, clientAddr)
		return
	}
	if len(allNameSpaceList) > 0 && !utils.IsContains(allNameSpaceList, nameSpace) {
		errorLogger.Println("集群不存在此命名空间")
		webSocketClientMap[clientAddr].WriteJSON(utils.GetI18nLang("en", "theNameSpaceNotExistInCluster"))
		webSocketClientMap[clientAddr].Close()
		delete(webSocketClientMap, clientAddr)
		return
	}

	//var ch = make(chan string)

	go func() {
		for {
			if _, ok := webSocketClientMap[clientAddr]; ok {
				_, message, err := webSocketClientMap[clientAddr].ReadMessage()
				if err != nil {
					infoLogger.Println("read:", err)
					if _, ok := webSocketClientMap[clientAddr]; ok {
						webSocketClientMap[clientAddr].Close()
					}
					delete(webSocketClientMap, clientAddr)
					break
				}
				infoLogger.Println(message)
			} else {
				break
			}
		}
	}()

	//当前时间秒
	currentSeconds := time.Now().Second()
	//起点时间秒
	startSinceSeconds := 1000000000000000

	//默认输出80条
	var tailLine int64 = 80
	podOptions := v1.PodLogOptions{
		Container: container,
		Follow:    true,
		TailLines: &tailLine,
	}

	for {
		//开始时间与当前时间之差
		difference := int64(startSinceSeconds - currentSeconds)
		podOptions.SinceSeconds = &difference
		stream, err := k8sClient.CoreV1().Pods(nameSpace).GetLogs(podName, &podOptions).Stream()
		if err != nil {
			errStr := err.Error()
			errorLogger.Printf("查询%s空间pod:%s 容器:%s日志失败:%s", nameSpace, podName, container, errStr)
			if _, ok := webSocketClientMap[clientAddr]; ok {
				//errMsg := utils.GetI18nLang("en", "tailPodLog_getContainerLogFail")
				//if match, e := regexp.MatchString(`pods "`+podName+`" not found`, errMsg); match && e == nil {
				//	errMsg = utils.GetI18nLang("en", "removePod_podNotFound")
				//
				//} else if match, e := regexp.MatchString(`container "`+container+`" is not valid for pod `+podName, errMsg); match && e == nil {
				//	errMsg = utils.GetI18nLang("en", "tailPodLog_containerNotFound")
				//}

				if _, ok := webSocketClientMap[clientAddr]; ok {
					//发送消息
					webSocketClientMap[clientAddr].WriteJSON(errStr)
					webSocketClientMap[clientAddr].Close()
				}
				delete(webSocketClientMap, clientAddr)
			}
			break
		}
		defer stream.Close()

		reader := bufio.NewReader(stream)

	read:
		for {
			line, err := reader.ReadBytes('\n')
			if err != nil {
				if err.Error() != "EOF" {
					infoLogger.Println(err.Error())
				}
				break read
			}
			str := utils.ReplaceAnsiCharOfString(string(line))
			str = strings.ReplaceAll(str, "\n", "")
			if _, ok := webSocketClientMap[clientAddr]; ok {
				//发送消息
				webSocketClientMap[clientAddr].WriteJSON(str)
			} else {
				break read
			}
			continue read
		}
		startSinceSeconds = time.Now().Second()
	}

}
