package org.springblade.webSocket;

import com.alibaba.fastjson.JSON;
import org.springblade.common.enums.AppConstant;
import org.springblade.webSocket.dto.Message;
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.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author cy-computer
 */
@ServerEndpoint("/websocket/{sid}")
@Component
public class WebSocketServer {

	/**
	 * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
	 */
	private static AtomicInteger onlineNum = new AtomicInteger();
	/**
	 * concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象。
	 */
	private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();


	/**
	 * 给指定用户发送消息
	 * @param sid
	 * @param message
	 */
	public void sendInfo(String sid, String message){
		Session session = sessionPools.get(sid);
		try {
			sendMessage(session, message);
		}catch (Exception e){
			e.printStackTrace();
		}
	}


	/**
	 * 群发消息
	 * @param message
	 */
	public void broadcast(String message){
		for (Session session: sessionPools.values()) {
			try {
				sendMessage(session, message);
			} catch(Exception e){
				e.printStackTrace();
				continue;
			}
		}
	}

	/**
	 * 发送消息
	 * @param session
	 * @param message
	 * @throws IOException
	 */
	private void sendMessage(Session session, String message) throws IOException {
		if(session != null){
			synchronized (session) {
				System.out.println("发送数据：" + message);
				session.getBasicRemote().sendText(message);
			}
		}
	}
	/**
	 * 成功建立连接的回调
	 * @param session
	 * @param sid
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam(value = "sid") String sid){
		sessionPools.put(sid, session);
		addOnlineCount();
		System.out.println(sid + "加入webSocket！当前连接数为" + onlineNum);
		//给客户端返回连接成功的消息
		Message message = new Message();
		message.setSid(sid);
		message.setContent("连接成功");
		message.setType(AppConstant.ChatType.SYSTEM_NOTIFY);
		this.sendInfo(sid, JSON.toJSONString(message,true));
	}

	/**
	 * 断开连接的回调
	 * @param sid
	 */
	@OnClose
	public void onClose(@PathParam(value = "sid") String sid){
		sessionPools.remove(sid);
		subOnlineCount();
		System.out.println(sid + "断开webSocket连接！当前连接数为" + onlineNum);
	}


	/**
	 * 客户端给服务端发送信息的回调
	 * @param message
	 * @throws IOException
	 */
	@OnMessage
	public void onMessage(String message) throws IOException{
		System.out.println("server get" + message);
		Message msg= JSON.parseObject(message, Message.class);
		msg.setDate(new Date());
		if (AppConstant.ChatType.GROUP_CHAT.equals(msg.getType())) {
			//群发消息
			broadcast(JSON.toJSONString(msg,true));
		} else {
			sendInfo(msg.getSid(), JSON.toJSONString(msg,true));
		}
	}

	/**
	 * 错误时的回调
	 * @param session
	 * @param throwable
	 */
	@OnError
	public void onError(Session session, Throwable throwable){
		System.out.println("发生错误");
		throwable.printStackTrace();
	}


	/**
	 * 增加连接人数
	 */
	public static void addOnlineCount(){
		onlineNum.incrementAndGet();
	}



	/**
	 * 减少连接人数
	 */
	public static void subOnlineCount() {
		onlineNum.decrementAndGet();
	}
}
