import { v4 } from 'uuid'

export interface WSMessageHandler {
    /**
     * Websocket端连接成功事件响应
     * @param sessionId socket会话ID
     * @param context 客户端连接时所有参数
     */
    onConnected(sessionId: string, context: any): Promise<any> ;
    /**
     * Websocket端连接关闭事件响应
     * @param sessionId socket会话ID
     * @param context 客户端连接时所有参数
     */
    onClosed(sessionId: string, context: any): Promise<any> ;
    /**
     * 响应接收到服务端发送的其他消息
     * @param msg 消息内容
     */
    onOtherMsg(msg: any, sessionId: string, context: any): Promise<any> ;
}


export class WSServiceBase {
    sessionId:string = v4();
    context:any = {};
    ws:any = null;
    protected messageHandler: WSMessageHandler = null;
    private wsTimeoutObj: any = null
    /**
     * 连接成功事件响应
     * @param event 
     */
    async onopen(event:any) {
        this.startWsPing();
        await this.messageHandler.onConnected(this.sessionId,this.context)
    }
    /**
     * 定时发送心跳消息
     */
    private startWsPing() {
        if (this.wsTimeoutObj) {
            clearInterval(this.wsTimeoutObj);
        }
        let self = this;
        this.wsTimeoutObj = setInterval(function () {
            if(self.ws.readyState !== 1){
                clearInterval(self.wsTimeoutObj);
                return;
            }
            self.ws.send('PING');
        }, 30000)//30s发送给服务器ping消息
    }
    /**
     * 接收到新消息响应
     * @param event 
     */
    async onmessage(event:any) {
        const receivedMsg = event.data;
        if (receivedMsg === 'PONG') {return;}//忽略心跳消息
        const msgBody = this.parseJSON(receivedMsg);
        if(typeof msgBody !== 'object'){
            await this.messageHandler.onOtherMsg(receivedMsg,this.sessionId,this.context)
            return
        }
        switch(msgBody.type){
            default: 
              await this.messageHandler.onOtherMsg(receivedMsg,this.sessionId, this.context) 
        }
    }
    /**
     * 连接关闭事件响应
     * @param event 
     */
    async onclose(event:any) {
        await this.messageHandler.onClosed(this.sessionId,this.context)
    }
    private parseJSON(txt) {
        try {return JSON.parse(txt)} catch (e) {}
        return txt
    }
    /**
     * 发送消息至服务端
     * @param msg 消息体
     */
    async sendMsg(msg: any){
        const ws = this.ws
        if (!ws) {
            throw new Error('未连接 Websocket');
        }
        ws.send(msg)
    }
}


