// Package ws -----------------------------
// @file      : client.go
// @author    : JJXu
// @contact   : wavingbear@163.com
// @time      : 2022/10/21 18:18:05
// -------------------------------------------
package ws

import (
	"context"
	"fmt"
	"github.com/gorilla/websocket"
	uuid "github.com/satori/go.uuid"
	"go.uber.org/zap"
	"log"
	"strings"
	"time"
)

var (
	// 注册事件最大等待时间
	limitRegisterWaitTime = time.Second * 6
	limitReadTime         = time.Second * 5
)

// NewClient 创建客户端实例
//
//	param userId 用户id
//	param uid 用户uuid
//	param conn 客户端websocket连接对象
//	return *Client
func NewClient(userId int64, uid string, conn *websocket.Conn, room *ChatRoom) *Client {
	uidobj, _ := uuid.NewV4()
	var v = &Client{
		Room:     room,
		UserId:   userId,
		Uuid:     uid,
		ClientId: strings.Replace(uidobj.String(), "-", "", -1),
		Conn:     conn,
		Send:     make(chan []byte, 500),
	}
	return v
}

type Client struct {
	Room      *ChatRoom       `json:"-" `
	UserId    int64           `json:"userId" `  //用户id
	Uuid      string          `json:"uuid"`     //画家uid
	ClientId  string          `json:"clientId"` //为用户不同设备分配不同的客户端ID
	Conn      *websocket.Conn `json:"-"`
	Send      chan []byte
	SessionId string `json:"sessionId"` //会话ID,同一个用户多客户端登录,会话ID相同
	Waiter    bool   `json:"waiter"`    //是否是客服
}

func (c *Client) Reading(ctx context.Context, handleFunc ...func(sourceData []byte, cli *Client)) {
	defer func() {
		c.Room.UnRegister <- c
		ctx.Done()
		return
	}()
	//c.Conn.SetReadLimit(maxMessageSize)
	c.Conn.SetReadDeadline(time.Now().Add(pongWait))
	//接收到ping命令后,更新读取时间
	c.Conn.SetPongHandler(func(string) error {
		c.Conn.SetReadDeadline(time.Now().Add(pongWait))
		return nil
	})
	for {
		msgType, byteData, err := c.Conn.ReadMessage()
		if msgType == -1 {
			return
		}
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
				log.Println("ws连接已关闭", zap.Error(err))
			}
			break
		}
		if handleFunc != nil {
			handleFunc[0](byteData, c)
		} else {
			HandleMessage(byteData, c)
		}
	}
}
func (c *Client) WriteWait() {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
		c.Conn.Close()
	}()

	for {
		select {
		case msg, ok := <-c.Send:
			if !ok {
				// 聊天室关闭了管道
				c.Conn.WriteControl(websocket.CloseMessage, []byte{}, time.Now().Add(writeWait))
				return
			}
			// 设置写入超时
			err := c.Conn.SetWriteDeadline(time.Now().Add(writeWait))
			fmt.Printf("设置写超时 err check:%v\n", err)
			fmt.Printf("发送消息:%+v\n", string(msg))
			err = c.Conn.WriteMessage(websocket.TextMessage, msg)
			fmt.Printf("发送消息结束 err check:%v\n", err)
		case <-ticker.C:
			fmt.Println("ping websocket client")
			err := c.Conn.SetWriteDeadline(time.Now().Add(writeWait))
			fmt.Printf("ping 设置写超时 err check:%v\n", err)
			if err := c.Conn.WriteControl(websocket.PingMessage, nil, time.Now().Add(pongWait)); err != nil {
				return
			}
		}
	}
}