package GmWeb

import (
	"Server-Core/Server/GameServer/Server/PlaneGame/Module"
	"sync"

	//"Server-Core/Server/GameServer/Server/PlaneGame/Module"
	message "Server-Core/Server/Message"
	"encoding/binary"

	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/golang/protobuf/proto"
	"github.com/gorilla/websocket"
	log "github.com/sirupsen/logrus"
)

func Cors() gin.HandlerFunc {
	return func(context *gin.Context) {
		//log.Info("收到请求")
		method := context.Request.Method
		context.Header("Access-Control-Allow-Origin", "*")
		context.Header("Access-Control-Allow-Headers", "Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild,access-control-allow-headers,access-control-allow-methods,access-control-allow-origin")
		context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT,PATCH, HEAD")
		context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		context.Header("Access-Control-Allow-Credentials", "true")

		// 允许放行OPTIONS请求
		if method == "OPTIONS" {
			context.AbortWithStatus(http.StatusNoContent)
		}
		//log.Info("context====", context)
		context.Next()
		/*context.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		context.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		context.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token")
		context.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
		context.Writer.Header().Set("Access-Control-Max-Age", "172800")
		context.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		context.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		context.Next()*/

	}
}
func Webinit(port string) {

	// mp := make(map[string]any, 2)
	// err = yaml.Unmarshal(dataBytes, mp)

	//gin.SetMode(gin.ReleaseMode)
	router := gin.Default()
	router.Use(Cors())
	router.POST("/dev/game/start", gameInit)
	router.GET("/dev/game/configReload", gameConfigReload)
	router.GET("/ping", ping)
	router.GET("/dev/game/getRoomPage", GetRoomPage)
	router.GET("/dev/game/getToken", Gettoken)
	router.GET("/dev/room/init", RoomInit)
	router.Run(port)
}
func GetRoomPage(c *gin.Context) {

	sql := Module.GetRoomPage(c)
	log.Print("接收到了===login1", sql)
	c.JSON(http.StatusOK, sql)
}

 func RoomInit(c *gin.Context) {

 	sql := Module.RoomInit2(c)
// 	//log.Print("接收到了===login1", sql)
 	c.JSON(http.StatusOK, sql)
 }
func Gettoken(c *gin.Context) {

	sql := Module.Gettoken(c)
	log.Print("接收到了===login1", sql)
	c.JSON(http.StatusOK, sql)
}

func gameInit(c *gin.Context) {

	sql := Module.GameInit(c)
	log.Print("接收到了===login1", sql)
	c.JSON(http.StatusOK, sql)
}
func gameConfigReload(c *gin.Context) {

	Module.ReloadConfig(c)
	var sql = Module.SqlResponse{
		Code:    200,
		Message: "成功",
	}
	c.JSON(http.StatusOK, sql)
}

var upGrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

var CmdExector map[int16]func(ws *websocket.Conn, data []byte) = make(map[int16]func(ws *websocket.Conn, data []byte))
var lock sync.Mutex

func ping(c *gin.Context) {

	// 升级get请求为webSocket协议
	ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
	
	log.Info("连接成功")
	//upGrader.Upgrade(c.Writer, c.Request, nil);

	if err != nil {
		return
	}
	defer ws.Close() //返回前关闭
	for {
		// 读取ws中的数据

		mt2, message2, err := ws.ReadMessage()
		if err != nil {
		//	println("err========",err.Error())
			//log.Info("收到了断开通知")
			//log.Printf("错误")
			//log.Info("错误", err)
			//log.Printf("有玩家退出1")
			player := Module.GamePlayers[Module.ClientUserIds[ws]]
			//log.Printf("有玩家退出", player)
			if nil != player {
				if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
					
					lock.Lock()
					if player.Status != 0 {
						Module.QuitRoom(player, ws, 0)
					}

					lock.Unlock()
				} else {
					lock.Lock()

					if player.Status != 0 {
						Module.QuitRoom(player, ws, 0)
					}
					lock.Unlock()
				}
			}

			//CloseNormalClosure           = 1000
			// CloseGoingAway               = 1001
			// CloseProtocolError           = 1002
			// CloseUnsupportedData         = 1003
			// CloseNoStatusReceived        = 1005
			// CloseAbnormalClosure         = 1006
			// CloseInvalidFramePayloadData = 1007
			// ClosePolicyViolation         = 1008
			// CloseMessageTooBig           = 1009
			// CloseMandatoryExtension      = 1010
			// CloseInternalServerErr       = 1011
			// CloseServiceRestart          = 1012
			// CloseTryAgainLater           = 1013
			// CloseTLSHandshake            = 1015

			/*else {
				// 连接异常关闭
				fmt.Println("连接异常关闭:", err)
			}*/
			//wsMap.delete();
			//break
		}
		//pkg_length, gateway_type, protocol_type, UID, protoBytes := unpkgData(message2) //解包
		if mt2 == websocket.BinaryMessage {
			//注册到map，统一解析错误
			_, protocol_type, protoBytes := unpkgData2(message2) //解包
			log.Info("msgId===", protocol_type)
			CmdExector[int16(protocol_type)](ws, protoBytes)

		}
	}
}

// 解密
func byteDencrypt(byteData []byte, len int) int32 {
	//测试位 []byte{48,191,8,0}
	//4-1-0  = 3  byteData[3] = 0
	//4-1-1  = 2  byteData[2] = 8
	//4-1-2  = 1  byteData[1] = 191
	//4-1-3  = 0  byteData[0] = 48
	//取最后一位
	x := int32(byteData[len-1])
	//len-1为第一个数没有进行位移，所以去掉循环
	for i := 0; i < len-1; i++ {
		index := len - 1 - i                //反向取数
		x = x<<8 + int32(byteData[index-1]) //保存上次计算结果
		//fmt.Println(x,i,index)
	}
	//fmt.Println(x)
	return x
}

// 解析客户端发来的数据包
// 返回参数: int32:长度 int32:主协议 int32:消息协议 int32:UID  []byte:proto二进制数据
func unpkgData(data []byte) (int32, int32, int32, int32, []byte) {
	pkg_length := byteDencrypt([]byte{data[0], data[1]}, 2)
	gateway_type := byteDencrypt([]byte{data[2], data[3]}, 2)
	protocol_type := byteDencrypt([]byte{data[4], data[5]}, 2)
	UID := byteDencrypt([]byte{data[6], data[7], data[8], data[9]}, 4)
	protoBytes := make([]byte, pkg_length-10)
	for i, _ := range protoBytes {
		protoBytes[i] = data[i+10]
	}
	return pkg_length, gateway_type, protocol_type, UID, protoBytes
}

// 解析客户端发来的数据包
// 返回参数: int32:长度 int32:主协议 int32:消息协议 int32:UID  []byte:proto二进制数据
func unpkgData2(data []byte) (uint32, uint16, []byte) {
	u := binary.BigEndian.Uint32(data[:4])
	datapkg2 := make([]byte, 2)
	datapkg2[0] = data[4]
	datapkg2[1] = data[5]
	u2 := binary.BigEndian.Uint16(datapkg2)
	protoBytes := make([]byte, len(data)-6)
	for i, _ := range protoBytes {
		protoBytes[i] = data[i+6]
	}
	req := &message.LoginReq{}
	proto.Unmarshal(protoBytes, req) //解包
	return u, u2, protoBytes
}
