package cn.com.ty.lift.push.websocket.handler;

import cn.com.ty.lift.common.constants.ApiConstants;
import cn.com.ty.lift.common.constants.WebSocketConstants;
import cn.com.ty.lift.common.model.TimeMessage;
import cn.com.ty.lift.push.message.service.TimeMessageService;
import cn.com.ty.lift.push.websocket.model.RealTimeMessage;
import cn.com.ty.lift.push.websocket.model.TimeMessageVo;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.socket.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TimeyMessageHandler implements WebSocketHandler {

    private TimeMessageService timeMessageService;

    public TimeyMessageHandler() {
    }

    public TimeyMessageHandler(TimeMessageService TimeMessageService) {
        this.timeMessageService = TimeMessageService;
    }

    //在线用户列表
    private static final Map<Long, WebSocketSession> users;

    static {
        users = new HashMap<>();
    }

    //新增socket
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        //用户登录连接后，将用户id放入到在线用户列表中
        Long userId = getCurrentUser(session);
        if (userId != null) {
            users.put(userId, session);
            //获取用户实时消息
            List<TimeMessage> timeMessageList = timeMessageService.list(new QueryWrapper<TimeMessage>()
                    .eq("view_flag", WebSocketConstants.IS_NOT_VIEW)
                    .eq("user_id", userId)
                    .eq("device_model", ApiConstants.DeviceModel.PC)
            );
            //将消息推送给用户
            pushMessageToUser(userId, timeMessageList);
        }
    }

    //接收socket信息
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) {

    }

    /**
     * @param TimeMessages 推送的消息
     * @return 是否推送成功
     * @description 保存用户信息，并将消息推送给多个用户
     * @date 2020/5/2 4:28 下午
     */
    public boolean saveAndPushMessageToUsers(List<TimeMessage> TimeMessages) {
        if (TimeMessages != null && TimeMessages.size() > 0) {
            //先将即使消息保存到数据库
            if (timeMessageService.saveBatch(TimeMessages)) {
                List<Long> userIds = new ArrayList<>();
                TimeMessages.forEach(TimeMessage -> {
                    userIds.add(TimeMessage.getUserId());
                });
                return pushMessageToUsers(userIds, TimeMessages);
            }
        }
        return false;
    }

    /**
     * @return boolean
     * @Author huangyuan
     * @Description 给多个用户推送消息
     * @Date 21:36 2019-04-19
     * @Param [userIds, TimeMessages, count]
     **/
    public static boolean pushMessageToUsers(List<Long> userIds, List<TimeMessage> timeMessages) {
        try {
            if (userIds != null && userIds.size() > 0) {
                for (Long userId : userIds) {
                    WebSocketSession session = users.get(userId);
                    if (session != null) {
                        //新建消息体
                        RealTimeMessage realTimeMessage;
                        if (timeMessages != null && timeMessages.size() > 0) {
                            //将消息实体转化为消息vo
                            realTimeMessage = new RealTimeMessage(transToVo(timeMessages));
                            realTimeMessage.setSize((long) timeMessages.size());
                        } else {
                            realTimeMessage = new RealTimeMessage();
                            realTimeMessage.setSize(0L);
                        }
                        session.sendMessage(new TextMessage(JSONUtil.parseObj(realTimeMessage).toString()));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }


    /**
     * @return boolean
     * @Author huangyuan
     * @Description 把消息推给单个用户
     * @Date 21:35 2019-04-19
     * @Param [userId, TimeMessages]
     **/
    public static boolean pushMessageToUser(Long userId, List<TimeMessage> TimeMessages) {
        List<Long> userIds = new ArrayList<>();
        userIds.add(userId);
        return pushMessageToUsers(userIds, TimeMessages);
    }

    /**
     * @return boolean
     * @Author huangyuan
     * @Description 给单独用户推送信息
     * @Date 00:35 2019-04-20
     * @Param [userId, TimeMessage]
     **/
    public static boolean pushMessageToUser(Long userId, TimeMessage TimeMessage) {
        List<TimeMessage> TimeMessageList = new ArrayList<>();
        TimeMessageList.add(TimeMessage);
        return pushMessageToUser(userId, TimeMessageList);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        System.out.println("连接出错");
        users.remove(getCurrentUser(session));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("连接已关闭：" + status);
        users.remove(getCurrentUser(session));
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 获取用户id，作为标识
     *
     * @param session
     * @return Long
     * @throws
     * @author huangy
     * @date 2018年9月18日
     */
    private Long getCurrentUser(WebSocketSession session) {
        String userId = (String) session.getAttributes().get(ApiConstants.CURRENT_USER_ID);
        if (StringUtils.isNotBlank(userId)) {
            return Long.parseLong(userId);
        }
        return null;
    }

    /**
     * @param
     * @return
     * @description 消息二次封装
     * @date 2020/6/1 4:27 下午
     */
    private static List<TimeMessageVo> transToVo(List<TimeMessage> timeMessageList) {
        List<TimeMessageVo> voList = new ArrayList<>();
        if (timeMessageList != null && timeMessageList.size() > 0) {
            timeMessageList.forEach(timeMessage -> {
                if (timeMessage.getId() != null) {
                    TimeMessageVo vo = new TimeMessageVo();
                    vo.setId(timeMessage.getId().toString());
                    vo.setContent(timeMessage.getContent());
                    vo.setCreateTime(timeMessage.getCreateTime());
                    vo.setCreateUserId(timeMessage.getCreateUserId());
                    vo.setDeviceModel(timeMessage.getDeviceModel());
                    vo.setUserId(timeMessage.getUserId());
                    vo.setViewFlag(timeMessage.getViewFlag());
                    vo.setType(timeMessage.getType());
                    voList.add(vo);
                }
            });
        }
        return voList;
    }

}
