package cn.iocoder.yudao.module.app.controller.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 维修APP消息监听
 * @author vinjor-M
 * @date 10:22 2024/10/17
**/
@ServerEndpoint(value = "/websocket/message/{tenantId}/{userId}")
@Component
public class NotifyMessageSocket {
    private final static Logger log = LoggerFactory.getLogger(NotifyMessageSocket.class);
    // 保存链接的session，key为用户名,value为对应的session名
    public static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();
    //关键代码，设置一个静态上下文属性appcontext
    private static ApplicationContext appcontext;
    public static void setAppcontext(ApplicationContext appcontext) {
        NotifyMessageSocket.appcontext = appcontext;
    }
    public static ApplicationContext getAppcontext() {
        return appcontext;
    }


    /**
     * 创建连接
     * 用于监听建立连接，当有客户端与该服务端点建立连接时，将会自回调该注解标注的方法
     * @param session
     * @param userId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "tenantId") String tenantId,@PathParam(value = "userId") String userId) {
        this.sessionMap.put(tenantId+"_"+userId,session);
        log.info("{}租户下用户{}已创建连接", tenantId,userId);
    }


    /**
     * 用于监听客户端向服务端发送消息，当客户端与服务端发送消息时，将会回调该注解标注的方法
     * {
     *     Stringitude:124.11,
     *     latitude:125.33,
     *     positionInfo:"山东省济南市市中区八一立交桥"
     * }
     * @param msg
     * @param userId
     */
    @OnMessage
    public void onMessage(String msg,@PathParam(value = "userId") String userId){
        System.out.println("消息通知+"+userId);
    }


    /**
     * 用于监听连接关闭，当客户端与该服务端点断开连接时，将会回调该注解标注的方法
     * @param session
     * @param userId
     */
    @OnClose
    public void onClose(Session session,@PathParam(value = "tenantId") String tenantId,@PathParam(value = "userId") String userId){
        this.sessionMap.remove(tenantId+"_"+userId);
    }


    /**
     * 用于监听该连接上的任何错误，当客户端与该服务端点的连接发生任何异常，都将回调该注解标注的方法
     * 注意该方法的参数必选Throwable，可选Sessiion以及0-n个String参数，且String参数需要使用@PathParam注解标注
     * @param throwable
     * @param tenantId 租户id
     * @param userId 用户id
     */
    @OnError
    public void onError(Throwable throwable,@PathParam(value = "tenantId") String tenantId,@PathParam(value = "userId") String userId){
        log.error("{}租户下用户{}已创建连接", tenantId,userId);
    }

    /**
     * 发送给指定的用户
     * @param message
     */
    public void sendMessage(String message, String tenantId,String userId) throws IOException {
        if (sessionMap.containsKey(tenantId+"_"+userId)){
            Session session = sessionMap.get(tenantId+"_"+userId);
            session.getAsyncRemote().sendText(message);
        }
    }


}
