package v1

import (
	"bytes"
	"context"
	"designs/app/common/request"
	"designs/global"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/vmihailenco/msgpack/v5"
	"io"
	"net/http"
	"strconv"
	"time"
)

func Websocket2(c *gin.Context) {
	//url := "192.168.1.139:9000/handle"
	url := "127.0.0.1:9000/handle"
	for i := 0; i <= 5000; i++ {
		time.Sleep(50 * time.Millisecond)

		go func() {
			openId := "1test00" + strconv.Itoa(i)

			time.Sleep(time.Millisecond)

			dial := "ws://" + url
			//fmt.Println(dial)
			c, _, err := websocket.DefaultDialer.Dial(dial, nil)
			if err != nil {
				global.App.Log.Error(err.Error())
				fmt.Println(err)
			}
			//defer c.Close()

			go func() {
				for {
					pong := ExplodeMsg(&MsgStruct{
						Type: MSG_TYPE_PING,
						Data: time.Now().UnixMilli(),
					})
					err = c.WriteMessage(websocket.TextMessage, pong)
					time.Sleep(time.Second * 10)
				}
			}()
			fmt.Println(openId, "登录成功，开始心跳")

			// 读取服务器的响应
			go ReadMsg(c)
		}()
	}

}

func Websocket(c *gin.Context) {
	form := request.Check(c, &struct {
		OpenId string `form:"openId" json:"openId" binding:""`
	}{})

	if form.OpenId == "" {
		form.OpenId = "1test00"
	}

	url := "127.0.0.1:8788"
	url = "lianliankan.ichunhao.cn"
	url = "nuoddzhise.ichunhao.cn"
	for i := 0; i <= 4000; i++ {
		openId := form.OpenId + strconv.Itoa(i)
		time.Sleep(time.Millisecond * 60)
		go TestWebsocket(openId, url)
	}

	//var i = 0
	//for {
	//	openId := "1test00" + strconv.Itoa(i)
	//	i++
	//	time.Sleep(time.Millisecond)
	//	go TestWebsocket(openId, url)
	//	i++
	//	go TestWebsocket(openId, url)
	//}
}

func Websocket1(c *gin.Context) {

	url := "dev1.ichunhao.cn"
	for i := 0; i <= 5000; i++ {
		openId := "1test00" + strconv.Itoa(i)
		time.Sleep(time.Millisecond * 10)
		go TestWebsocket(openId, url)
	}

	//var i = 0
	//for {
	//	openId := "7test00" + strconv.Itoa(i)
	//	i++
	//	time.Sleep(time.Millisecond)
	//	go TestWebsocket(openId)
	//	i++
	//	go TestWebsocket(openId)
	//}
}

func TestWebsocket(openId string, url string) {
	var token string
	//http://101.42.6.84:8787
	//http://127.0.0.1:8788   dev.ichunhao.cn

	gid := "tt_fpdz3"
	token = global.App.Redis.Get(context.Background(), openId+"userId").Val()

	if token == "" {
		//请求登录接口，获取token
		reportDat := map[string]string{
			"code": openId,
			"gid":  gid,
			"pf":   "web",
		}

		//请求接口获取token
		// /v1/user/getSysTime     /v1/user/login
		content, err := CurlPost("http://"+url+"/v1/user/login", reportDat, nil)
		if err != nil {
			global.App.Log.Error(err.Error())
			fmt.Println(err)
		}

		var resp struct {
			Data struct {
				Token string `json:"token"`
			} `json:"data"`
		}
		str2oErr := json.Unmarshal([]byte(content), &resp)
		if str2oErr != nil {
			global.App.Log.Error(str2oErr.Error())
			fmt.Println(err)
		}
		if resp.Data.Token == "" {
			fmt.Println(content)
		}

		global.App.Redis.Set(context.Background(), openId+"userId", resp.Data.Token, time.Hour*3)

		token = resp.Data.Token

		//fmt.Println(content)
	}
	//fmt.Println(openId, "登录成功，开始心跳")
	//return

	//创建一个WebSocket客户端连接到服务器
	//  192.168.1.139:8788

	if token == "" {
		fmt.Println("token is empty")
		return
	}
	dial := "ws://" + url + "/v1/handle?token=" + token
	//fmt.Println(dial)
	c, _, err := websocket.DefaultDialer.Dial(dial, nil)
	if err != nil {
		global.App.Log.Error(err.Error())
		fmt.Println(err)
	}
	//defer c.Close()

	go func() {
		////set_team
		//msg := ExplodeMsg(&MsgStruct{
		//	Type: MSG_TYPE_SET_TEAM,
		//	Data: 4,
		//})
		//err = c.WriteMessage(websocket.BinaryMessage, msg)
		//
		////match
		//msg = ExplodeMsg(&MsgStruct{
		//	Type: MSG_TYPE_MATCH,
		//	Data: 2,
		//})
		//err = c.WriteMessage(websocket.TextMessage, msg)
		//
		//time.Sleep(time.Second * 10)
		////MSG_TYPE_MATCH
		//
		//for i := 1; i <= 100; i++ {
		//	msg = ExplodeMsg(&MsgStruct{
		//		Type: MSG_TYPE_UPDATE_USER_GAMEDATA,
		//		Data: map[string]interface{}{
		//			"data": map[string]string{
		//				"aa": "bbb",
		//				"cc": "dddd",
		//			},
		//			"userKey": gid + "||web||" + openId,
		//		},
		//	})
		//	//
		//	//msg = ExplodeMsg(&MsgStruct{
		//	//	Type: MSG_TYPE_TALK,
		//	//	Data: "你好你好你好",
		//	//})
		//
		//	err = c.WriteMessage(websocket.BinaryMessage, msg)
		//	time.Sleep(time.Second)
		//}
		//
		////离开
		//msg = ExplodeMsg(&MsgStruct{
		//	Type: MSG_TYPE_ROOM_EXIT,
		//	Data: "",
		//})
		//err = c.WriteMessage(websocket.TextMessage, msg)

		for {
			pong := ExplodeMsg(&MsgStruct{
				Type: MSG_TYPE_PING,
				Data: time.Now().UnixMilli(),
			})
			err = c.WriteMessage(websocket.TextMessage, pong)
			time.Sleep(time.Second)
		}

	}()
	fmt.Println(openId, "登录成功，开始心跳")

	// 读取服务器的响应
	go ReadMsg(c)
}

type MsgStruct struct {
	Type string      `msgpack:"type" json:"type"`
	Data interface{} `msgpack:"data" json:"data"`
}

func ExplodeMsg(msg *MsgStruct) []byte {
	//data, _ := json.Marshal(msg)

	data, _ := msgpack.Marshal(msg)
	return data
}

func ReadMsg(c *websocket.Conn) {

	for {
		_, _, err := c.ReadMessage()
		if err != nil {
			global.App.Log.Error(err.Error())
			fmt.Println(err)
		}

		//fmt.Printf("%s\n", message)
	}
}

func CurlPost(requestUrl string, requestBody interface{}, headerMap map[string]string) (string, error) {
	//转换json
	jsonBytes, err := json.Marshal(requestBody)
	if err != nil {
		return "", err
	}

	//创建请求
	req, err := http.NewRequest("POST", requestUrl, bytes.NewReader(jsonBytes))
	if err != nil {
		return "", err
	}
	//设置请求头
	req.Header.Set("Content-Type", "application/json;charset=UTF-8")
	for k, v := range headerMap {
		//req.Header.Set("Accept-Encoding", "gzip, deflate, br")
		req.Header.Set(k, v)
	}
	//发送请求
	clt := http.Client{Timeout: 60 * time.Second}
	res, err := clt.Do(req)
	if err != nil {
		return "", err
	}
	//获取结果
	body, err := io.ReadAll(res.Body)
	data := string(body)

	return data, err

}

const (
	MSG_TYPE_PING = "ping" //心跳
	MSG_TYPE_PONG = "pong" //心跳回传

	MSG_TYPE_TALK             = "c2s_talk"                 //消息  -- 发送给所有人
	MSG_TYPE_TALK_RES         = "s2c_talk"                 //消息  -- 服务端回发消息
	MSG_TYPE_MSG              = "c2s_message"              //消息  -- 发送给所有人
	MSG_TYPE_MSG_TO_HOST      = "c2s_message_to_host"      //消息  -- 发送给主机
	MSG_TYPE_MSG_WITHOUT_SELF = "c2s_message_without_self" //消息  -- 发送给除自己以外的人
	MSG_TYPE_EXIT             = "exit"                     //退出

	MSG_TYPE_MATCH     = "c2s_match"     //开始匹配
	MSG_TYPE_SET_TEAM  = "c2s_set_team"  //创建组队
	MSG_TYPE_JOIN_TEAM = "c2s_join_team" //加入组队
	MSG_TYPE_EXIT_TEAM = "c2s_exit_team" //离开组队

	MSG_TYPE_LOGIN_SUCCESS = "s2c_login_success" //登录成功后，服务器回传给前端
	MSG_TYPE_MATCH_SUCCESS = "s2c_match_success" //匹配到对手后，提示匹配成功，加入房间
	MSG_TYPE_TEAM_SUCCESS  = "s2c_team_success"  //进入房间后，提示
	MSG_TYPE_MATCH_CANCEL  = "c2s_match_cancel"  //取消匹配
	MSG_TYPE_ROOM_EXIT     = "c2s_room_exit"     //用户离开房间

	MSG_TYPE_UPDATE_ROOM_GAMEDATA = "c2s_update_room_gameData" //更新房间的游戏信息
	MSG_TYPE_UPDATE_USER_GAMEDATA = "c2s_update_user_gameData" //更新用户的游戏信息

	MSG_TYPE_ROOM_GAMEDATA_CHANGE = "s2c_room_gameData_change" //房间游戏信息修改，广播给所有玩家
	MSG_TYPE_USER_GAMEDATA_CHANGE = "s2c_user_gameData_change" //房间游戏信息修改，广播给所有玩家

	MSG_TYPE_TEAM_USER_JOIN   = "s2c_team_user_join"   //队伍用户加入房间，通知其他人
	MSG_TYPE_TEAM_USER_EXIT   = "s2c_team_user_exit"   //队伍用户离开房间，通知其他人
	MSG_TYPE_USER_DISCONNECT  = "s2c_user_disconnect"  //队伍用户掉线，通知其他人
	MSG_TYPE_USER_RECONNECT   = "s2c_user_reconnect"   //队伍用户重连，通知其他人
	MSG_TYPE_TEAM_CHANGE_HOST = "s2c_team_change_host" //队伍更换房主
	MSG_TYPE_ROOM_CHANGE_HOST = "s2c_room_change_host" //房间更换房主

	MSG_TYPE_ERROR           = "s2c_error"           //有错误的时候专用
	MSG_TYPE_TEAM_JOIN_FAIL  = "s2c_join_team_fail"  //加入队伍失败时
	MSG_TYPE_TEAM_LEFT_FAIL  = "s2c_left_team_fail"  //离开队伍失败时
	MSG_TYPE_CLOSE_ROOM_FAIL = "s2c_close_room_fail" //关闭房间失败

	MSG_TYPE_USER_MATCH        = "s2c_match"        //用户进入匹配队列
	MSG_TYPE_USER_MATCH_CANCEL = "s2c_match_cancel" //用户离开匹配队列

	MSG_TYPE_KICK_OUT = "c2s_kick_out" //房主踢人出房间

	MSG_TYPE_READY     = "c2s_ready"     //准备开始
	MSG_TYPE_READY_RES = "s2c_ready"     //准备开始回发
	MSG_TYPE_NOT_READY = "s2c_not_ready" //有人没准备

	MSG_TYPE_READY_CANCEL     = "c2s_ready_cancel" //取消准备
	MSG_TYPE_READY_CANCEL_RES = "c2s_ready_cancel" //取消准备回发

	MSG_TYPE_CLOSE_ROOM  = "c2s_close_room"  //发送消息准备关闭房间
	MSG_TYPE_ROOM_CLOSED = "s2c_room_closed" //房间已关闭
	MSG_TYPE_EXIT_ROOM   = "s2c_exit_room"   //用户离开房间

	MSG_TYPE_TO_BACKED     = "c2s_to_backed"     //切换到后台
	MSG_TYPE_BACKED_RETURN = "c2s_backed_return" //从后台回来

	MSG_TYPE_SETTLEMENT = "s2c_settlement" //游戏结算消息
	MSG_TYPE_FINISH     = "c2s_finish"     //玩家完成游戏
	MSG_TYPE_FINISH_RES = "s2c_finish"     //玩家完成游戏回发

	MSG_TYPE_RANK_DATA     = "c2s_rank_data" //查询排行榜
	MSG_TYPE_RANK_DATA_RES = "s2c_rank_data" //查询排行榜回发

	MSG_TYPE_RECEIVE_REWARD     = "c2s_receive_reward" //领取奖励
	MSG_TYPE_RECEIVE_REWARD_RES = "s2c_receive_reward"

	MSG_TYPE_SEASON     = "c2s_season"
	MSG_TYPE_SEASON_RES = "s2c_season"
)
