package com.uavps.framework.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.uavps.common.config.RuoYiConfig;
import com.uavps.common.utils.StringUtils;
import com.uavps.common.utils.spring.SpringUtils;
import com.uavps.common.utils.uuid.Seq;
import com.uavps.framework.udp.TaskInfo;
import com.uavps.framework.udp.UdpClientService;
import com.uavps.framework.udp.UdpServerService;
import com.uavps.framework.udp.utils.UdpDataUtils;
import com.uavps.system.domain.UavpsTask;
import com.uavps.system.service.IUavpsAircraftService;
import com.uavps.system.service.IUavpsAlgorithmParameterService;
import com.uavps.system.service.IUavpsTaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.time.Instant;
import java.util.Date;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * websocket 消息处理
 *
 * @author ruoyi
 */
@Component
@ServerEndpoint("/websocket/message")
public class WebSocketServer {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    UdpServerService udpServerService = new UdpServerService();

    UdpClientService udpClientService = new UdpClientService();

    private IUavpsAircraftService uavpsAircraftService = SpringUtils.getBean(IUavpsAircraftService.class);

    private IUavpsAlgorithmParameterService algorithmParameterService = SpringUtils.getBean(IUavpsAlgorithmParameterService.class);

    private IUavpsTaskService uavpsTaskService = SpringUtils.getBean(IUavpsTaskService.class);;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) throws Exception {
        log.info("\nWebSocket建立连接 - {}", session);
        //启动服务，接收算法返回的数据
        CompletableFuture.runAsync(() -> {
            udpServerService.receive(session);
        });

        //发送初始化参数给算法
        //String str = "BB 14 03 01 00 01 01 00 D2 57 05 08 B4 18 6D 2F 64 00 0A 00 14 00 0A 00 15 CD 5B 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 44 1B";
        //udpClientService.send(str);
    }

    /**
     * 连接关闭时处理
     */
    @OnClose
    public void onClose(Session session) {
        log.info("\nWebSocket关闭连接 - {}", session);
        closeUdpServer();
    }

    /**
     * 抛出异常时处理
     */
    @OnError
    public void onError(Session session, Throwable exception) throws Exception {
        log.info("\nWebSocket连接异常信息 - {}", exception);
        closeUdpServer();
    }

    /**
     * 服务器接收到客户端消息时调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        if (session != null) {
            try {
                if (message.startsWith("REPLAY:")) {
                    long baseTime = Instant.now().toEpochMilli();
                    //重放，获取数据库轨迹数据
                    String bizId = message.substring(7);
                    UavpsTask uavpsTask = uavpsTaskService.selectUavpsTaskByBizId(Long.parseLong(bizId));
                    String filePath = uavpsTask.getFilePath();
                    try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                            // 解析时间戳和数据
                            if (line.length() > 11 && line.charAt(10) == ':') {
                                    long timestamp = Long.parseLong(line.substring(0, 10));
                                    String json = line.substring(11);
                                    long currentTime = Instant.now().toEpochMilli();
                                    long targetTime = baseTime + timestamp;
                                    // 计算需要等待的时间
                                    long waitTime = targetTime - currentTime;
                                    if (waitTime > 0) {
                                        TimeUnit.MILLISECONDS.sleep(waitTime);
                                    }
                                    session.getBasicRemote().sendText(json);
                            } else {
                                System.err.println("Invalid line format: " + line);
                            }
                        }
                    } catch (IOException e) {
                        log.error("File reading error id : {}", bizId, e);
                    }
                } else if (message.startsWith("RUN:")) {
                    String paramId = message.substring(4);
//                    UavpsAlgorithmParameter param = algorithmParameterService.selectUavpsAlgorithmParameterById(Long.parseLong(paramId));
                    long bizId = Long.parseLong(paramId);

                    UavpsTask uavpsTask = uavpsTaskService.selectUavpsTaskByBizId(bizId);
                    uavpsTask.setBizType(UavpsTask.START);
                    ObjectMapper mapper = new ObjectMapper();
                    String json = null;
                    try {
                        json = mapper.writeValueAsString(uavpsTask);
                        logger.info("RUN json :{}", json);
                    } catch (Exception e) {
                        logger.error("WebSocketServer.onMessage to json error", e);
                    }
                    String filePath = StringUtils.format("{}/{}/{}.{}", RuoYiConfig.getTaskPath(),
                            bizId, Seq.getId(Seq.uploadSeqType), "txt");
                    uavpsTask.setFilePath(filePath);
                    uavpsTask.setStartTime(new Date());
                    uavpsTask.setStatus(UavpsTask.RUNNING);
                    uavpsTaskService.updateUavpsTask(uavpsTask);
                    // 初始化 坐标转换参数
                    TaskInfo.INSTANCE.reset(bizId, filePath);
                    assert json != null;
                    udpClientService.send(json);
//                    UdpDataUtils.bizId = IdUtils.simpleUUID();
                } else if (message.startsWith("TRANSFORMATION:")) {
//                    closeUdpServer();

                    String bizId = message.substring(15);
                    UavpsTask uavpsTask = new UavpsTask();
                    uavpsTask.setBizId(Long.parseLong(bizId));
                    uavpsTask.setBizType(UavpsTask.CHANGE);
                    ObjectMapper mapper = new ObjectMapper();
                    String json = null;
                    try {
                        json = mapper.writeValueAsString(uavpsTask);
                        logger.info("TRANSFORMATION json :{}", json);
                    } catch (Exception e) {
                        logger.error("WebSocketServer.onMessage to json error", e);
                    }
                    assert json != null;
                    udpClientService.send(json);
//                    this.onOpen(session);
                } else if (message.startsWith("DISAPPEAR:")) {
                    String param = message.substring(10);
                    String[] paramAry = param.split(",");
                    UavpsTask uavpsTask = new UavpsTask();
                    uavpsTask.setBizId(Long.parseLong(paramAry[0]));
                    uavpsTask.setBizType(UavpsTask.DISAPPEAR);
                    for (String s : paramAry) {
                        uavpsTask.getNumbers().add(Integer.parseInt(s));
                    }
                    ObjectMapper mapper = new ObjectMapper();
                    String json = null;
                    try {
                        json = mapper.writeValueAsString(uavpsTask);
                        logger.info("DISAPPEAR json :{}", json);
                    } catch (Exception e) {
                        logger.error("WebSocketServer.onMessage to json error", e);
                    }
                    assert json != null;
                    udpClientService.send(json);
                } else if (message.startsWith("SHOW:")) {
                    String param = message.substring(5);
                    String[] paramAry = param.split(",");
                    UavpsTask uavpsTask = new UavpsTask();
                    uavpsTask.setBizId(Long.parseLong(paramAry[0]));
                    uavpsTask.setBizType(UavpsTask.SHOW);
                    for (String s : paramAry) {
                        uavpsTask.getNumbers().add(Integer.parseInt(s));
                    }
                    ObjectMapper mapper = new ObjectMapper();
                    String json = null;
                    try {
                        json = mapper.writeValueAsString(uavpsTask);
                        logger.info("SHOW json :{}", json);
                    } catch (Exception e) {
                        logger.error("WebSocketServer.onMessage to json error", e);
                    }
                    assert json != null;
                    udpClientService.send(json);
                } else if (message.startsWith("END:")) {
                    Long bizId = Long.parseLong(message.substring(4));
                    UavpsTask uavpsTask = new UavpsTask();
                    uavpsTask.setBizId(bizId);
                    uavpsTask.setBizType(UavpsTask.END);
                    ObjectMapper mapper = new ObjectMapper();
                    String json = null;
                    try {
                        json = mapper.writeValueAsString(uavpsTask);
                        logger.info("END json :{}", json);
                    } catch (Exception e) {
                        logger.error("WebSocketServer.onMessage to json error", e);
                    }
                    assert json != null;
                    udpClientService.send(json);
                    uavpsTask = uavpsTaskService.selectUavpsTaskByBizId(bizId);
                    uavpsTask.setEndTime(new Date());
                    uavpsTask.setStatus(UavpsTask.COMPLETED);
                    uavpsTaskService.updateUavpsTask(uavpsTask);
                } else {
                    session.getBasicRemote().sendText(message);
                }
            } catch (IOException | InterruptedException e) {
                log.error("\nWebSocket发送消息异常: ", e);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            log.info("\n用户未登录！");
        }
    }

    private void closeUdpServer() {
        // do noting
    }
}
