package com.qmth.themis.exam.listener.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.qmth.themis.business.bean.status.MonitorStatusBean;
import com.qmth.themis.business.cache.ExamRecordCacheUtil;
import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.MqDto;
import com.qmth.themis.business.dto.WebsocketDto;
import com.qmth.themis.business.entity.TEExamStudent;
import com.qmth.themis.business.entity.TEExamStudentLog;
import com.qmth.themis.business.entity.TIeExamInvigilateNotice;
import com.qmth.themis.business.entity.TOeExamRecord;
import com.qmth.themis.business.enums.*;
import com.qmth.themis.business.service.TEExamStudentLogService;
import com.qmth.themis.business.service.TEExamStudentService;
import com.qmth.themis.business.service.TIeExamInvigilateNoticeService;
import com.qmth.themis.business.service.TMRocketMessageService;
import com.qmth.themis.business.util.JacksonUtil;
import com.qmth.themis.common.contanst.Constants;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.exam.listener.service.MqOeLogicService;
import com.qmth.themis.exam.websocket.WebSocketMobileServer;
import com.qmth.themis.exam.websocket.WebSocketOeServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: mq 考生端执行逻辑 impl
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/7/31
 */
@Service
public class MqOeLogicServiceImpl implements MqOeLogicService {
    private final static Logger log = LoggerFactory.getLogger(MqOeLogicServiceImpl.class);

    @Resource
    TMRocketMessageService tmRocketMessageService;

    @Resource
    TEExamStudentLogService teExamStudentLogService;

    @Resource
    TEExamStudentService teExamStudentService;

    @Resource
    TIeExamInvigilateNoticeService tIeExamInvigilateNoticeService;

    /**
     * 强制离线交卷持久化逻辑
     *
     * @param s
     * @param webSocketMap
     * @param mqDto
     * @param key
     * @return
     */
    @Transactional
    public Map<String, Object> oeMonitorFinishLogicPersisted(Object s,
                                                             ConcurrentHashMap<String, WebSocketOeServer> webSocketMap,
                                                             MqDto mqDto,
                                                             String key) {
        Map<String, Object> map = null;
        Long recordId = Long.parseLong(String.valueOf(s));
        //获取考试记录的客户端websocketId
        String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
        if (Objects.nonNull(clientWebsocketId) && Objects.nonNull(webSocketMap.get(clientWebsocketId))) {
            map = new HashMap<>();
            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
            WebSocketOeServer webSocketOeServer = webSocketMap.get(clientWebsocketId);
            ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
            if ((Objects.nonNull(examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.JUNK, examRecordStatusEnum))
                    && Objects.nonNull(webSocketOeServer.getRecordId())
                    && webSocketOeServer.getRecordId().longValue() == recordId.longValue()) {
                map.put("form", mqDto.getObjName());
                map.put(SystemConstant.WEB_SOCKET_OE_SERVER, webSocketOeServer);
                map.put(SystemConstant.RECORD_ID, recordId);
                map.put(SystemConstant.MESSAGE, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get(SystemConstant.TYPE))).getCode());

                TEExamStudentLog teExamStudentLog = new TEExamStudentLog(mqDto.getType().name(), "监考老师[" + mqDto.getObjName() + "]强制离线（交卷）", mqDto.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentId, recordId, mqDto.getType().getCode(), null, null, null, null, null, null);
                teExamStudentLogService.save(teExamStudentLog);

                tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
            }
        }
        return map;
    }

    /**
     * 预警交卷持久化逻辑
     *
     * @param s
     * @param webSocketMap
     * @param mqDto
     * @param key
     * @return
     */
    @Transactional
    public Map<String, Object> oeWarningFinishLogicPersisted(Object s,
                                                             ConcurrentHashMap<String, WebSocketOeServer> webSocketMap,
                                                             MqDto mqDto,
                                                             String key) {
        Map<String, Object> map = null;
        Long recordId = Long.parseLong(String.valueOf(s));
        String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
        if (Objects.nonNull(clientWebsocketId) && Objects.nonNull(webSocketMap.get(clientWebsocketId))) {
            map = new HashMap<>();
            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
            WebSocketOeServer webSocketOeServer = webSocketMap.get(clientWebsocketId);
            ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
            if ((Objects.nonNull(examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.JUNK, examRecordStatusEnum))
                    && Objects.nonNull(webSocketOeServer.getRecordId())
                    && webSocketOeServer.getRecordId().longValue() == recordId.longValue()) {
                map.put(SystemConstant.WEB_SOCKET_OE_SERVER, webSocketOeServer);
                map.put(SystemConstant.RECORD_ID, recordId);
                map.put(SystemConstant.BREACH_STATUS, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get(SystemConstant.TYPE))).getCode());

                TEExamStudentLog teExamStudentLog = new TEExamStudentLog(mqDto.getType().name(), mqDto.getType().getCode(), mqDto.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentId, recordId, mqDto.getType().getCode(), null, null, null, null, null, null);
                teExamStudentLogService.save(teExamStudentLog);

                tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
            }
        }
        return map;
    }

    /**
     * 点对点消息持久化逻辑
     *
     * @param webSocketMap
     * @param mqDto
     * @param key
     * @return
     */
    @Transactional
    public Map<String, Object> oeImClusteringLogicPersisted(ConcurrentHashMap<String, WebSocketOeServer> webSocketMap,
                                                            MqDto mqDto,
                                                            String key) {
        Map<String, Object> map = null;
        Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
        String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
        if (Objects.nonNull(clientWebsocketId) && Objects.nonNull(webSocketMap.get(clientWebsocketId))) {
            map = new HashMap<>();
            Long examId = ExamRecordCacheUtil.getExamId(recordId);
            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
            Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
            WebSocketOeServer webSocketOeServer = webSocketMap.get(clientWebsocketId);
            ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
            if ((Objects.nonNull(examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.JUNK, examRecordStatusEnum))
                    && Objects.nonNull(webSocketOeServer.getRecordId())
                    && webSocketOeServer.getRecordId().longValue() == recordId.longValue()) {
                Map<String, Object> prop = mqDto.getProperties();
                map.put(SystemConstant.RECORD_ID, recordId);
                map.put("from", mqDto.getObjName());
                map.put(SystemConstant.WEB_SOCKET_OE_SERVER, webSocketOeServer);
                map.put(SystemConstant.TYPE, prop.get(SystemConstant.TYPE));
                map.put(SystemConstant.CONTENT, prop.get(SystemConstant.CONTENT));
                TIeExamInvigilateNotice tIeExamInvigilateNotice = new TIeExamInvigilateNotice(examId, examActivityId, recordId, Long.parseLong(String.valueOf(prop.get(SystemConstant.FORM_USER_ID))), examStudentId, MessageTypeEnum.valueOf(String.valueOf(prop.get(SystemConstant.TYPE)).toUpperCase()), String.valueOf(prop.get(SystemConstant.CONTENT)));
                tIeExamInvigilateNoticeService.saveOrUpdate(tIeExamInvigilateNotice);

                tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
            }
        }
        return map;
    }

    /**
     * 监考强制活体验证持久化逻辑
     *
     * @param webSocketMap
     * @param mqDto
     * @param key
     * @return
     */
    @Transactional
    public Map<String, Object> oeLivenessVerifyLogicPersisted(ConcurrentHashMap<String, WebSocketOeServer> webSocketMap,
                                                              MqDto mqDto,
                                                              String key) {
        Map<String, Object> map = null;
        Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
        String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
        if (Objects.nonNull(clientWebsocketId) && Objects.nonNull(webSocketMap.get(clientWebsocketId))) {
            map = new HashMap<>();
            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
            WebSocketOeServer webSocketOeServer = webSocketMap.get(clientWebsocketId);
            ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
            if ((Objects.nonNull(examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)
                    && !Objects.equals(ExamRecordStatusEnum.JUNK, examRecordStatusEnum))
                    && Objects.nonNull(webSocketOeServer.getRecordId())
                    && webSocketOeServer.getRecordId().longValue() == recordId.longValue()) {
                map.put(SystemConstant.RECORD_ID, recordId);
                map.put(SystemConstant.WEB_SOCKET_OE_SERVER, webSocketOeServer);

                TEExamStudentLog teExamStudentLog = new TEExamStudentLog(mqDto.getType().name(), mqDto.getType().getCode(), mqDto.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentId, recordId, mqDto.getType().getCode(), null, null, null, null, null, null);
                teExamStudentLogService.save(teExamStudentLog);

                tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
            }
        }
        return map;
    }

    /**
     * oe逻辑
     *
     * @param mqDto
     * @param key
     */
    @Override
    public void execMqOeLogic(MqDto mqDto, String key) throws NoSuchAlgorithmException, IOException {
        ConcurrentHashMap<String, WebSocketOeServer> webSocketMap = WebSocketOeServer.getWebSocketMap();
        String tag = mqDto.getTag();
        if (Objects.equals(MqTagEnum.OE_MONITOR_FINISH.name(), tag)) {//强制离线交卷
            Set examRecordId = JacksonUtil.readJson(String.valueOf(mqDto.getBody()), Set.class);
            examRecordId.forEach(s -> {
                Map<String, Object> map = oeMonitorFinishLogicPersisted(s, webSocketMap, mqDto, key);
                if (Objects.nonNull(map) && Objects.nonNull(map.get(SystemConstant.WEB_SOCKET_OE_SERVER))) {
                    WebSocketOeServer webSocketOeServer = (WebSocketOeServer) map.get(SystemConstant.WEB_SOCKET_OE_SERVER);
                    WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_STOP_EXAM.name(), map);
                    webSocketOeServer.sendMessage(websocketDto);
                }
            });
        } else if (Objects.equals(MqTagEnum.OE_WARNING_FINISH.name(), tag)) {//预警交卷
            Set examRecordId = JacksonUtil.readJson(String.valueOf(mqDto.getBody()), Set.class);
            examRecordId.forEach(s -> {
                Map<String, Object> map = oeWarningFinishLogicPersisted(s, webSocketMap, mqDto, key);
                if (Objects.nonNull(map) && Objects.nonNull(map.get(SystemConstant.WEB_SOCKET_OE_SERVER))) {
                    WebSocketOeServer webSocketOeServer = (WebSocketOeServer) map.get(SystemConstant.WEB_SOCKET_OE_SERVER);
                    WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.BREACH_STOP_EXAM.name(), map);
                    webSocketOeServer.sendMessage(websocketDto);
                }
            });
        } else if (Objects.equals(MqTagEnum.OE_IM_CLUSTERING.name(), tag)) {//点对点消息
            Map<String, Object> map = oeImClusteringLogicPersisted(webSocketMap, mqDto, key);
            if (Objects.nonNull(map) && Objects.nonNull(map.get(SystemConstant.WEB_SOCKET_OE_SERVER))) {
                WebSocketOeServer webSocketOeServer = (WebSocketOeServer) map.get(SystemConstant.WEB_SOCKET_OE_SERVER);
                WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_NOTICE.name(), map);
                webSocketOeServer.sendMessage(websocketDto);
            }
        } else if (Objects.equals(MqTagEnum.OE_IM_BROADCASTING.name(), tag)) {//广播消息
            JSONArray jsonArray = JSONArray.parseArray(String.valueOf(mqDto.getBody()));
            Set<String> examStudentIdentitySet = jsonArray.toJavaObject(Set.class);
            log.info("examStudentIdentitySet:{}", JacksonUtil.parseJson(examStudentIdentitySet));
        } else if (Objects.equals(MqTagEnum.OE_LIVENESS_VERIFY.name(), tag)) {//监考强制活体验证
            Map<String, Object> map = oeLivenessVerifyLogicPersisted(webSocketMap, mqDto, key);
            if (Objects.nonNull(map) && Objects.nonNull(map.get(SystemConstant.WEB_SOCKET_OE_SERVER))) {
                WebSocketOeServer webSocketOeServer = (WebSocketOeServer) map.get(SystemConstant.WEB_SOCKET_OE_SERVER);
                WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_LIVENESS_VERIFY.name(), map);
                webSocketOeServer.sendMessage(websocketDto);
            }
        } else if (Objects.equals(MqTagEnum.OE_WEBSOCKET_MOBILE_ANSWER_READY.name(), tag)//移动端拍照/录音扫描完成
                || Objects.equals(MqTagEnum.OE_WEBSOCKET_MOBILE_ANSWER_UPLOAD.name(), tag)//移动端拍照/录音上传成功
                || Objects.equals(MqTagEnum.OE_WEBSOCKET_EXAM_STOP.name(), tag)//考试结束
                || Objects.equals(MqTagEnum.MONITOR_START.name(), tag)//监控开始
                || Objects.equals(MqTagEnum.MONITOR_STOP.name(), tag)//监控结束
                || Objects.equals(MqTagEnum.OE_WEBSOCKET_MOBILE_MONITOR_STATUS.name(), tag)//通知客户端移动端当前监控状态
                || Objects.equals(MqTagEnum.EXAM_EXIT.name(), tag)) {//考试退出
            Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
            TOeExamRecord tOeExamRecord = null;
            String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
            if (Objects.isNull(clientWebsocketId)) {
                tOeExamRecord = SystemConstant.getExamRecord(recordId);
                clientWebsocketId = tOeExamRecord.getClientWebsocketId();
            }
            Map<String, Object> prop = mqDto.getProperties();
            if (Objects.nonNull(prop) && prop.size() > 0) {
                prop.put(SystemConstant.RECORD_ID, recordId);
            }
            if (Objects.nonNull(clientWebsocketId) && Objects.nonNull(webSocketMap.get(clientWebsocketId))) {
                WebSocketOeServer webSocketOeServer = webSocketMap.get(clientWebsocketId);
                ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
                if (Objects.isNull(examRecordStatusEnum)) {
                    tOeExamRecord = Objects.isNull(tOeExamRecord) ? SystemConstant.getExamRecord(recordId) : tOeExamRecord;
                    examRecordStatusEnum = tOeExamRecord.getStatus();
                }
                if (Objects.nonNull(examRecordStatusEnum)
                        && Objects.nonNull(webSocketOeServer.getRecordId())
                        && webSocketOeServer.getRecordId().longValue() == recordId.longValue()) {
                    WebsocketDto websocketDto = null;
                    switch (tag.toUpperCase()) {
                        case "OE_WEBSOCKET_MOBILE_ANSWER_READY":
                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_ANSWER_READY.name(), prop);
                            webSocketOeServer.sendMessage(websocketDto);
                            break;
                        case "OE_WEBSOCKET_MOBILE_ANSWER_UPLOAD":
                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_ANSWER_UPLOAD.name(), prop);
                            webSocketOeServer.sendMessage(websocketDto);
                            break;
                        case "OE_WEBSOCKET_EXAM_STOP":
                            if (!Objects.equals(ExamRecordStatusEnum.ANSWERING, examRecordStatusEnum)) {
                                websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_STOP.name(), prop);
                                webSocketOeServer.sendMessage(websocketDto);
                                SystemConstant.clientMonitorStatusStop(recordId);
                                Boolean removeWebsocket = (Boolean) prop.get(SystemConstant.REMOVE_WEBSOCKET);
                                if (Objects.nonNull(removeWebsocket) && removeWebsocket) {
                                    WebSocketOeServer.close(webSocketOeServer);
                                }
                            }
                            break;
                        case "MONITOR_START":
                            MonitorVideoSourceEnum source = MonitorVideoSourceEnum.valueOf((String) prop.get(Constants.HEADER_SOURCE));
                            MonitorStatusBean monitorStatusBean = ExamRecordCacheUtil.getMonitorStatusBean(recordId, source);
                            if ((Objects.nonNull(monitorStatusBean)
                                    && Objects.nonNull(monitorStatusBean.getTimestamp())
                                    && mqDto.getTimestamp().longValue() >= monitorStatusBean.getTimestamp().longValue())
                                    && (!Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
                                    && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)
                                    && !Objects.equals(ExamRecordStatusEnum.JUNK, examRecordStatusEnum))) {
                                websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_START.name(), prop);
                                webSocketOeServer.sendMessage(websocketDto);
                            }
                            break;
                        case "MONITOR_STOP":
                            source = MonitorVideoSourceEnum.valueOf((String) prop.get(Constants.HEADER_SOURCE));
                            monitorStatusBean = ExamRecordCacheUtil.getMonitorStatusBean(recordId, source);
                            if ((Objects.nonNull(monitorStatusBean)
                                    && Objects.nonNull(monitorStatusBean.getTimestamp())
                                    && mqDto.getTimestamp().longValue() >= monitorStatusBean.getTimestamp().longValue())
                                    && (!Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
                                    && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)
                                    && !Objects.equals(ExamRecordStatusEnum.JUNK, examRecordStatusEnum))) {
                                websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_STOP.name(), prop);
                                webSocketOeServer.sendMessage(websocketDto);
                                //                                ConcurrentHashMap<String, WebSocketMobileServer> webSocketMobileMap = WebSocketMobileServer.getWebSocketMap();
//
//                                String mobileWebsocketId = null;
////                                WebsocketStatusEnum websocketStatusEnum = null;
//                                if (source == MonitorVideoSourceEnum.MOBILE_FIRST) {
//                                    mobileWebsocketId = ExamRecordCacheUtil.getMobileFirstWebsocketId(recordId);
////                                    websocketStatusEnum = ExamRecordCacheUtil.getMobileFirstWebsocketStatus(recordId);
//                                } else if (source == MonitorVideoSourceEnum.MOBILE_SECOND) {
//                                    mobileWebsocketId = ExamRecordCacheUtil.getMobileSecondWebsocketId(recordId);
////                                    websocketStatusEnum = ExamRecordCacheUtil.getMobileSecondWebsocketStatus(recordId);
//                                }
////                                if (Objects.nonNull(websocketStatusEnum) && websocketStatusEnum == WebsocketStatusEnum.ON_LINE) {
//                                WebSocketMobileServer webSocketMobileServer = webSocketMobileMap.get(mobileWebsocketId + "-" + source.name());
//                                Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
//                                ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
//                                Optional.ofNullable(examStudentCacheBean).orElseThrow(() -> new BusinessException("考生数据为空"));
//
//                                SystemConstant.mobileMonitorStatusStop(examStudentCacheBean.getStudentId(), recordId, true);
//                                WebSocketMobileServer.close(webSocketMobileServer);
////                                }
                            }
                            break;
                        case "OE_WEBSOCKET_MOBILE_MONITOR_STATUS":
                            String monitorVideoSource = ExamRecordCacheUtil.getMonitorVideoSource(recordId);
                            List<String> monitorVideoSourceList = null;
                            if (Objects.nonNull(monitorVideoSource) && !Objects.equals(monitorVideoSource.trim().replaceAll(" ", ""), "")) {
                                monitorVideoSourceList = Arrays.asList(monitorVideoSource.trim().toUpperCase().replaceAll(" ", "").split(","));
                            }
                            if (Objects.nonNull(monitorVideoSourceList) && monitorVideoSourceList.size() > 0 && monitorVideoSourceList.contains(MonitorVideoSourceEnum.MOBILE_FIRST.name())) {
                                prop.put(MonitorVideoSourceEnum.MOBILE_FIRST.name().toLowerCase(), ExamRecordCacheUtil.getMonitorStatus(recordId, MonitorVideoSourceEnum.MOBILE_FIRST));
                            }
                            if (Objects.nonNull(monitorVideoSourceList) && monitorVideoSourceList.size() > 0 && monitorVideoSourceList.contains(MonitorVideoSourceEnum.MOBILE_SECOND.name())) {
                                prop.put(MonitorVideoSourceEnum.MOBILE_SECOND.name().toLowerCase(), ExamRecordCacheUtil.getMonitorStatus(recordId, MonitorVideoSourceEnum.MOBILE_SECOND));
                            }
                            websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_STATUS.name(), prop);
                            webSocketOeServer.sendMessage(websocketDto);
                            break;
                        case "EXAM_EXIT":
                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_EXIT.name(), prop);
                            webSocketOeServer.sendMessage(websocketDto);
                            break;
                        default:
                            break;
                    }
                    tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
                }
            }
        }
    }

    /**
     * oe mobile逻辑
     *
     * @param mqDto
     * @param key
     */
    @Override
    public void execMqOeMobileLogic(MqDto mqDto, String key) throws NoSuchAlgorithmException, IOException {
        String tag = mqDto.getTag();
        if (Objects.equals(MqTagEnum.EXAM_STOP.name(), tag)//考试退出
                || Objects.equals(MqTagEnum.EXAM_START.name(), tag)) {//考试开始
//                || Objects.equals(MqTagEnum.EXAM_AUDIO_MOBILE.name(), tag)) {//考试语音
//            examStartAndStopAndAudioLogic(mqDto, key);
            examStartAndStopLogic(mqDto, key);
        }
    }

    /**
     * 考试开始和停止和语音逻辑
     *
     * @param mqDto
     * @param key
     * @throws NoSuchAlgorithmException
     * @throws IOException
     */
    public void examStartAndStopLogic(MqDto mqDto, String key) throws NoSuchAlgorithmException, IOException {
        ConcurrentHashMap<String, WebSocketMobileServer> webSocketMap = WebSocketMobileServer.getWebSocketMap();
        String tag = mqDto.getTag();
        Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
        TOeExamRecord tOeExamRecord = null;
        ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
        if (Objects.isNull(examRecordStatusEnum)) {
            tOeExamRecord = SystemConstant.getExamRecord(recordId);
            examRecordStatusEnum = tOeExamRecord.getStatus();
        }
        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
        Long studentId = null;
        if (Objects.isNull(examStudentId)) {
            tOeExamRecord = Objects.isNull(tOeExamRecord) ? SystemConstant.getExamRecord(recordId) : tOeExamRecord;
            TEExamStudent teExamStudent = teExamStudentService.getById(tOeExamRecord.getExamStudentId());
            studentId = teExamStudent.getStudentId();
        } else {
            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
            Optional.ofNullable(examStudentCacheBean).orElseThrow(() -> new BusinessException("考生数据为空"));
            studentId = examStudentCacheBean.getStudentId();
        }

        String mobileFirstWebsocketId = ExamRecordCacheUtil.getMobileFirstWebsocketId(recordId);
        if (Objects.isNull(mobileFirstWebsocketId)) {
            tOeExamRecord = Objects.isNull(tOeExamRecord) ? SystemConstant.getExamRecord(recordId) : tOeExamRecord;
            mobileFirstWebsocketId = tOeExamRecord.getMobileFirstWebsocketId();
        }
        Map<String, Object> prop = mqDto.getProperties();
        if (Objects.nonNull(prop) && prop.size() > 0) {
            prop.put(SystemConstant.RECORD_ID, recordId);
        }
        if (Objects.nonNull(mobileFirstWebsocketId) && Objects.nonNull(webSocketMap.get(mobileFirstWebsocketId))) {
            WebSocketMobileServer webSocketFirstMobileServer = webSocketMap.get(mobileFirstWebsocketId);
            if (Objects.nonNull(examRecordStatusEnum)
                    && Objects.nonNull(webSocketFirstMobileServer.getRecordId())
                    && webSocketFirstMobileServer.getRecordId().longValue() == recordId.longValue()) {
                WebsocketDto websocketDto = null;
                switch (tag.toUpperCase()) {
                    case "EXAM_STOP":
                        if (!Objects.equals(ExamRecordStatusEnum.ANSWERING, examRecordStatusEnum)) {
                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_STOP.name(), prop);
                            webSocketFirstMobileServer.sendMessage(websocketDto);
                            SystemConstant.mobileMonitorStatusStop(studentId, recordId, false);
                            Boolean removeWebsocket = (Boolean) prop.get(SystemConstant.REMOVE_WEBSOCKET);
                            if (Objects.nonNull(removeWebsocket) && removeWebsocket) {
                                WebSocketMobileServer.close(webSocketFirstMobileServer);
                            }
                        }
                        break;
                    case "EXAM_START":
                        if (!Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
                                && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)
                                && !Objects.equals(ExamRecordStatusEnum.JUNK, examRecordStatusEnum)) {
                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_START.name(), prop);
                            webSocketFirstMobileServer.sendMessage(websocketDto);
                        }
                        break;
//                    case "EXAM_AUDIO_MOBILE":
//                        if (!Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
//                                && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)) {
//                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_AUDIO.name(), mqDto.getProperties());
//                            webSocketFirstMobileServer.sendMessage(websocketDto);
//                        }
//                        break;
                    default:
                        break;
                }
                tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
            }
        }
        String mobileSecondWebsocketId = ExamRecordCacheUtil.getMobileSecondWebsocketId(recordId);
        if (Objects.isNull(mobileSecondWebsocketId)) {
            tOeExamRecord = Objects.isNull(tOeExamRecord) ? SystemConstant.getExamRecord(recordId) : tOeExamRecord;
            mobileSecondWebsocketId = tOeExamRecord.getMobileSecondWebsocketId();
        }
        if (Objects.nonNull(mobileSecondWebsocketId) && Objects.nonNull(webSocketMap.get(mobileSecondWebsocketId))) {
            WebSocketMobileServer webSocketSecondMobileServer = webSocketMap.get(mobileSecondWebsocketId);
            if (Objects.nonNull(examRecordStatusEnum)
                    && Objects.nonNull(webSocketSecondMobileServer.getRecordId())
                    && webSocketSecondMobileServer.getRecordId().longValue() == recordId.longValue()) {
                WebsocketDto websocketDto = null;
                switch (tag.toUpperCase()) {
                    case "EXAM_STOP":
                        if (!Objects.equals(ExamRecordStatusEnum.ANSWERING, examRecordStatusEnum)) {
                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_STOP.name(), prop);
                            webSocketSecondMobileServer.sendMessage(websocketDto);
                            SystemConstant.mobileMonitorStatusStop(studentId, recordId, false);
                            Boolean mobileRemoveWebsocket = (Boolean) prop.get(SystemConstant.REMOVE_WEBSOCKET);
                            if (Objects.nonNull(mobileRemoveWebsocket) && mobileRemoveWebsocket) {
                                WebSocketMobileServer.close(webSocketSecondMobileServer);
                            }
                        }
                        break;
                    case "EXAM_START":
                        if (!Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
                                && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)
                                && !Objects.equals(ExamRecordStatusEnum.JUNK, examRecordStatusEnum)) {
                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_START.name(), prop);
                            webSocketSecondMobileServer.sendMessage(websocketDto);
                        }
                        break;
//                    case "EXAM_AUDIO_MOBILE":
//                        if (!Objects.equals(ExamRecordStatusEnum.PERSISTED, examRecordStatusEnum)
//                                && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)) {
//                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_AUDIO.name(), mqDto.getProperties());
//                            webSocketSecondMobileServer.sendMessage(websocketDto);
//                        }
//                        break;
                    default:
                        break;
                }
                tmRocketMessageService.saveMqMessageSuccess(mqDto, key);
            }
        }
    }
}