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

import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.module.rescue.service.IRescueDriverInfoService;
import com.alibaba.fastjson.JSONObject;
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.util.concurrent.ConcurrentHashMap;


/**`1
 * @Author: chuxia0811
 * @Date: 2023/7/9 10:21
 * @Description :
 */
@ServerEndpoint(value = "/websocket/rescueDriver/{driverId}")
@Component
public class RescueDriverSocket {
    private final static Logger log = LoggerFactory.getLogger(RescueDriverSocket.class);
    // 保存链接的session，key为用户名,value为对应的session名
    private ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();
    //关键代码，设置一个静态上下文属性appcontext
    private static ApplicationContext appcontext;

    public RescueDriverSocket(SpringUtil springUtil) {

    }

    public static void setAppcontext(ApplicationContext appcontext) {
        RescueDriverSocket.appcontext = appcontext;
    }
    public static ApplicationContext getAppcontext() {
        return appcontext;
    }

    public void init(){

    }

    /**
     * 创建连接
     * 用于监听建立连接，当有客户端与该服务端点建立连接时，将会自回调该注解标注的方法
     * @param session
     * @param driverId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "driverId") String driverId) {
        this.sessionMap.put(driverId,session);
        //更新司机在线状态
        IRescueDriverInfoService rescueDriverInfoService = SpringUtil.getBean(IRescueDriverInfoService.class);
        rescueDriverInfoService.topLine(Long.parseLong(driverId));
        log.info("用户{}已创建连接", driverId);
    }


    /**
     * 用于监听客户端向服务端发送消息，当客户端与服务端发送消息时，将会回调该注解标注的方法
     * {
     *     longitude:124.11,
     *     latitude:125.33,
     *     positionInfo:"山东省济南市市中区八一立交桥"
     * }
     * @param msg
     * @param driverId
     */
    @OnMessage
    public void onMessage(String msg,@PathParam(value = "driverId") String driverId){
        JSONObject requestMsg = JSONObject.parseObject(msg);
        //更新司机位置信息
        IRescueDriverInfoService rescueDriverInfoService = SpringUtil.getBean(IRescueDriverInfoService.class);
        rescueDriverInfoService.updatePosition(Long.parseLong(driverId),requestMsg);
        log.info("用户{}发来消息:{}",driverId,msg);
    }


    /**
     * 用于监听连接关闭，当客户端与该服务端点断开连接时，将会回调该注解标注的方法
     * @param session
     * @param driverId
     */
    @OnClose
    public void onClose(Session session,@PathParam(value = "driverId") String driverId){
        this.sessionMap.remove(driverId);
        //更新司机在线状态
        IRescueDriverInfoService rescueDriverInfoService = SpringUtil.getBean(IRescueDriverInfoService.class);
        rescueDriverInfoService.downLine(Long.parseLong(driverId));

        log.info("用户{}已关闭连接", driverId);
    }


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

}
