package me.zhengjie.modules.system.service.impl;//package me.zhengjie.modules.system.service.webstocket;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.config.WebSocketConfig;
import me.zhengjie.modules.security.config.enums.CapabilitieEnum;
import me.zhengjie.modules.security.config.enums.MethodEnum;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.domain.dto.BusDeviceQueryCriteria;
import me.zhengjie.modules.system.service.WebSocketService;
import me.zhengjie.modules.system.service.webstocket.req.WebSocketReqDTO;
import me.zhengjie.modules.system.service.webstocket.req.WebSocketReqData;
import me.zhengjie.utils.SecurityUtils;
import me.zhengjie.utils.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;

@ServerEndpoint("/webSocket/vue")
@Slf4j
@Component
public class WebSocketVueServiceImpl extends WebSocketService {

    // 初始化
    @PostConstruct
    public void init() {
        log.info(">>> 设备初始化");
        refreshDeviceList();
        log.info("<<< 设备初始化");
    }

    @Scheduled(fixedRate = 60000)
    public void refreshDeviceList() {
        deviceList = new ArrayList<>();
        List<BusDevice> devices = myDeviceService.queryAll(new BusDeviceQueryCriteria());
        for (BusDevice device : devices) {
            deviceList.add(device.getDeviceSn());
        }
    }

    /**
     * 连接调用方法
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        this.channel = session.getId();
        log.info("【VUE服务端】连接成功：channel={}", channel);
        clients.put(channel, this);
    }

    /**
     * 连接关闭调用的方法
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        WebSocketService collect = getSocket(session.getId());
        if (null == collect) { return; }
        log.info("【VUE服务端】连接断开：channel={}", collect.channel);
    }

    /**
     * 连接异常时
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        WebSocketService collect = getSocket(session.getId());
        if (null == collect) { return; }
        log.info("【VUE服务端】发现异常：channel={}", collect.channel);
        error.printStackTrace();
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(Session session, String message) {
        WebSocketService collect = getSocket(session.getId());
        if (null == collect) { return; }
        long time = System.currentTimeMillis();
        log.info("【VUE服务端】收到消息：channel={}，message={}", collect.channel, message);
        log.info("【" + time + "-----------------------------】");
        serviceMessageHandle(message);
        log.info("【" + time + "-----------------------------】");
    }

    private void serviceMessageHandle(String message) {
        if (StringUtils.isEmpty(message)) { return; }
        // 发送的指令
        message = message.replace("\\", "");
        WebSocketReqDTO param = null;
        MethodEnum method = null;
        try {
            param = JSON.parseObject(message, WebSocketReqDTO.class);
            method = param.getMethod();
        } catch (Exception e) { e.printStackTrace(); }
        if (null == method || method != MethodEnum.request) {
            log.info("<<< 请求类型有误，忽略");
            return;
        }
        String deviceSn = param.getMainboardID();
        // 只关心已有的设备
        if (!deviceList.contains(deviceSn)) {
            log.info("<<< 设备【{}】在系统未找到，忽略", deviceSn);
            return;
        }
        String command = param.getCommand();
        if (StringUtils.isEmpty(command)) {
            log.info("<<< 命令为空，忽略");
            return;
        }
        String commandStr = null;
        long sysTimeLong = System.currentTimeMillis();
        // 刷新
        if (command.equals(CapabilitieEnum.REFRESH.name())) {
            WebSocketReqData data = new WebSocketReqData();
            data.setCmd(0);
            data.setData(new HashMap());
            data.setType(0);
            data.setRequestID(sysTimeLong + "");
            data.setMainboardID(deviceSn);
            data.setTimeStamp(sysTimeLong);
            WebSocketReqDTO req = new WebSocketReqDTO();
            req.setTopic(WebSocketConfig.TOPIC_PREFIX + "/" + MethodEnum.request + "/" + deviceSn);
            req.setData(data);
            commandStr = JSON.toJSONString(req);
        }
        // 暂停
        else if (command.equals(CapabilitieEnum.PAUSE.name())) {

        }
        // 继续
        else if (command.equals(CapabilitieEnum.CONTINUE.name())) {

        }
        // 退出
        else if (command.equals(CapabilitieEnum.EXIT.name())) {

        }
        // 图片
        else if (command.equals(CapabilitieEnum.IMAGE.name())) {
            Map<String, Integer> dataParam = new HashMap<>();
            dataParam.put("Type", 0);
            WebSocketReqData data = new WebSocketReqData();
            data.setCmd(385);
            data.setData(dataParam);
            data.setRequestID(sysTimeLong + "");
            data.setMainboardID(deviceSn);
            data.setTimeStamp(sysTimeLong);
            WebSocketReqDTO req = new WebSocketReqDTO();
            req.setTopic(WebSocketConfig.TOPIC_PREFIX + "/" + MethodEnum.request + "/" + deviceSn);
            req.setData(data);
            commandStr = JSON.toJSONString(req);
        }
        // 视频
        else if (command.equals(CapabilitieEnum.OPEN_VIDEO.name()) || command.equals(CapabilitieEnum.CLOSE_VIDEO.name())) {
            int uIndex = (videoUser.contains(session.getId())) ? new ArrayList<>(videoUser).indexOf(session.getId()) : videoUser.size();
            Map<String, Object> dataParam = new HashMap<>();
            dataParam.put("Enable", command.equals(CapabilitieEnum.OPEN_VIDEO.name()) ? 1 : 0);
            dataParam.put("UserId", uIndex);
            WebSocketReqData data = new WebSocketReqData();
            data.setCmd(386);
            data.setData(dataParam);
            data.setRequestID(sysTimeLong + "");
            data.setMainboardID(deviceSn);
            data.setTimeStamp(sysTimeLong);
            WebSocketReqDTO req = new WebSocketReqDTO();
            req.setTopic(WebSocketConfig.TOPIC_PREFIX + "/" + MethodEnum.request + "/" + deviceSn);
            req.setData(data);
            commandStr = JSON.toJSONString(req);
            // 记录用户打开视频
            if (command.equals(CapabilitieEnum.OPEN_VIDEO.name()))
                videoUser.add(session.getId());
            // 移除用户记录
            else
                videoUser.remove(session.getId());
        }
        else {
            log.info("<<< 命令类型未找到，忽略");
            return;
        }
        sendThirdPartyMessage(commandStr);
    }

    // 发送消息给第三方
    private void sendThirdPartyMessage(String message) {
        for (Map.Entry<String, WebSocketService> entry : clients.entrySet()) {
            try {
                WebSocketService server = entry.getValue();
                String channel = server.channel;
                Session session = server.session;
                if (!channel.equals(WebSocketConfig.TOPIC_PREFIX) || null == session || !session.isOpen()) { continue; }
                log.info(">>> 发送指令消息给第三方：channel={}，message={}", channel, message);
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
                log.info("<<< 发送指令消息给第三方-异常 原因：", e);
            }
        }
    }
}