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> ;
    /**
     * 响应接收到服务端发送的[MsgC]类型消息
     * @param data 消息内容
     */
    onMsgMsgC(data: any, sessionId: string, context: any): Promise<any> ;
    /**
     * 响应接收到服务端发送的[MsgD]类型消息
     * @param data 消息内容
     */
    onMsgMsgD(data: any, sessionId: string, context: any): Promise<any> ;
    /**
     * 响应接收到服务端发送的其他消息
     * @param msg 消息内容
     */
    onOtherMsg(msg: any, sessionId: string, context: any): Promise<any> ;
}


export class WSServiceBase {
    protected sessionId:string = v4();
    protected context:any = {};
    protected ws:any = null;
    protected messageHandler: WSMessageHandler = null;
    /**
     * 设置消息处理器
     * @param messageHandler 消息处理器
     */
    useMessageHandler(messageHandler: WSMessageHandler):WSServiceBase {
        this.messageHandler = messageHandler
        return this;
    }
    /**
     * 创建WebSocket连接
     * @param wsUrl WebsocketURL
     * @param msg 消息体
     */
    async connectWS(wsUrl:string,context: any = {}): Promise<any>{
        if(!this.messageHandler) throw new Error('未实现 WSMessageHandler');
        this.context = context;
        this.sessionId = v4();
        this.ws = new WebSocket(this.processWsUrl(wsUrl));
        this.ws.onopen = this.onopen
        this.ws.onmessage = this.onmessage
        this.ws.onclose = this.onclose
    }
    private processWsUrl(wsUrl:string): string{
        const params = 'sessionId=' + this.sessionId + '&' + Object.entries(obj).map(([key, val]) => `${key}=${val }`).join('&');
        if (url.indexOf("?") > -1) {
            return url + "&" + params
        }else{
            return url + "?" + params
        }
    }
    /**
     * 连接成功事件响应
     * @param event 
     */
    async onopen(event:any) {
        await this.messageHandler.onConnected(this.sessionId,this.context)
    }
    /**
     * 接收到新消息响应
     * @param event 
     */
    async onmessage(event:any) {
        const receivedMsg = event.data;
        const msgType = receivedMsg.type;
        if(!msgType){
            await this.messageHandler.onOtherMsg(receivedMsg,this.sessionId, this.context)
            return
        }
        switch(receivedMsg.type){
            case 'MsgC':
              await this.messageHandler.onMsgMsgC(receivedMsg.data,this.sessionId, this.context)
              break;
            case 'MsgD':
              await this.messageHandler.onMsgMsgD(receivedMsg.data,this.sessionId, this.context)
              break;
            default: 
              await this.messageHandler.onOtherMsg(receivedMsg,this.sessionId, this.context) 
        }
    }
    /**
     * 连接关闭事件响应
     * @param event 
     */
    async onclose(event:any) {
        await this.messageHandler.onClosed(this.sessionId,this.context)
    }
    /**
     * 发送[MsgC]类型消息至服务端
     * @param data 消息内容
     */
    async sendMsgMsgC(data: any){
        await this.sendMsg({type:'MsgC',data})
    }
    /**
     * 发送[MsgD]类型消息至服务端
     * @param data 消息内容
     */
    async sendMsgMsgD(data: any){
        await this.sendMsg({type:'MsgD',data})
    }
    /**
     * 发送消息至服务端
     * @param msg 消息体
     */
    async sendMsg(msg: any){
        const ws = this.ws
        if (!ws) {
            throw new Error('未连接 Websocket');
        }
        ws.send(msg)
    }
}


