package com.rf.psychological.socket;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zzf
 * @description:
 * @date 2021/10/11 10:26
 */
@Slf4j
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocketServer {
    private static  HashMap<String,String>control;
    private static List<String> loginUser;
    static{
        control = new HashMap<>();
    }
    /** 记录当前在线连接数 */
    private static AtomicInteger onlineCount = new AtomicInteger(0);
    /**
     * 用来存放每个客户端对应的WebSocketServer对象
     */
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    /**
     *与某个客户端的连接会话需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 用来接收userId
     */
    private String userId;
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session , @PathParam("userId") String userId) throws IOException {
        this.session = session;
        this.userId = userId;
        //判断用户是否已经登录对应的角色

        if(loginUser==null){
            loginUser = new ArrayList<>();
            loginUser.add(userId);
        }else{
            if(loginUser.contains(userId)){
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code","201");
                jsonObject.put("msg","您选择的角色"+(userId.contains("doc")?"医生":"普通用户")+"已存在，请重新选择");
                sendMessage(jsonObject.toJSONString());
                return;
            }else{
                loginUser.add(userId);
            }
        }


        if(webSocketMap.containsKey(userId)){
            webSocketMap.remove(userId);
            webSocketMap.put(userId,this);
        }else{
            webSocketMap.put(userId,this);
            addOnlineCount();
        }
        if(userId.indexOf("doc")>0){
            //判断医生端是否是被控端
            boolean flag = false;
            for (Map.Entry entry:control.entrySet()) {
                if(entry.getValue().equals(userId)){
                    flag = true;
                }
            }
            if(!flag){
                control.put(userId,userId.replace("doc","patient"));
            }else{
                control.put(userId.replace("doc","patient"),userId);
            }
        }
        log.info("用户连接：{},当前在线人数为：{}",userId,getOnlineCount());
        try{
            sendMessage("连接成功");
        }catch(IOException e ) {
            log.error("用户：{},网络异常",userId);
        }
        System.out.println("onOpen-----");
        for (Map.Entry entry:control.entrySet()) {
            System.out.println(entry.getKey()+"----"+entry.getValue());
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            subOnlineCount();
            control.remove(userId);
        }
        System.out.println("onClose---");
        if(loginUser != null ){
            loginUser.remove(userId);
        }
        log.info("有一连接关闭：{}，当前在线人数为：{}", userId, webSocketMap.size());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     *            客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {


        JSONObject respJson = new JSONObject();
        System.out.println("onMessage----");
        for (Map.Entry entry:control.entrySet()) {
            System.out.println(entry.getKey()+"----"+entry.getValue());
        }

        log.info("用户消息:" + userId + ",报文:" + message);
//        sendMessage("发送成功");
        if (!StringUtils.isEmpty(message)) {
            try {
                JSONObject jsonObject = JSONObject.parseObject(message);
                jsonObject.put("fromUserId", this.userId);
                String toUserId = jsonObject.getString("toUserId");
                if (!StringUtils.isEmpty(toUserId) && webSocketMap.containsKey(toUserId)) {
                    //判断谁给谁发的逻辑的地方
                    if(this.userId.indexOf("doc") >= 0){
                        //医生端向用户端发送消息，message=control 表示医生端控制用户端 message=disControl表示医生解除对用户端的控制
                        JSONObject messageJson = JSONObject.parseObject(message).getJSONObject("message");
                        //控制切换
                        if(messageJson.containsKey("master")){
                            if(messageJson.getBoolean("master")){
                                control.remove(toUserId);
                                control.put(this.userId,toUserId);
                                webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                                respJson.put("msg","发送成功！");
                            }else if(!messageJson.getBoolean("master")){
                                control.remove(this.userId);
                                control.put(toUserId,userId);
                                webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                                respJson.put("msg","发送成功！");
                            }


                        }else{
                            if(control.get(this.userId) != null){
                                webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                                respJson.put("msg","发送成功！");

                            }

                        }

                    }else{
                        if(control.get(this.userId) != null){
                            webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                            respJson.put("msg","发送成功！");
                        }
                    }
                } else {
                    log.error("请求的 userId:" + toUserId + "不在该服务器上！");
                    respJson.put("msg","发送失败，请求的用户"+toUserId+"不在该服务器上！");
                }
                sendMessage(respJson.toJSONString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    public static synchronized AtomicInteger getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount.getAndIncrement();
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount.getAndDecrement();
    }
}
