package com.ningdatech.carapi.radar.helper;

import com.google.common.collect.Lists;
import com.ningdatech.basic.util.StrPool;
import com.ningdatech.carapi.radar.model.vo.RadarDataVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * @author CMM
 * @since 2024/11/08 10:15
 */
@Component
@RequiredArgsConstructor
public class RadarDataHelper {

    // 将16进制字符串转换为字节数组
    public byte[] hexStringToByteArray(String s) {
        // 确保字符串长度为偶数
        if (s.length() % 2 != 0) {
            // 如果长度为奇数，移除最后一个字符
            s = s.substring(0, s.length() - 1);
        }
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // 如果输入的字符不是16进制字符，跳过
            if (!Character.isDigit(s.charAt(i)) && !Character.isLetter(s.charAt(i))) {
                continue;
            }
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    // 以16进制字节数组解析数据帧并提取指定位置指定字节数的数据
    public byte[] extractHexData(String hexFrame, int dataOffset, int dataLength) {
        byte[] frameBytes = hexStringToByteArray(hexFrame);
        // 检查数据长度是否超出帧的范围
        if (dataOffset + dataLength > frameBytes.length) {
            throw new IllegalArgumentException("Data length exceeds frame boundary");
        }
        // 提取数据
        byte[] extractedData = new byte[dataLength];
        System.arraycopy(frameBytes, dataOffset, extractedData, 0, dataLength);
        return extractedData;
    }

    // 在字节数组中查找特定模式
    public int findPattern(byte[] array, byte[] pattern) {
        for (int i = 0; i < array.length - pattern.length + 1; i++) {
            boolean found = true;
            for (int j = 0; j < pattern.length; j++) {
                if (array[i + j] != pattern[j]) {
                    found = false;
                    break;
                }
            }
            if (found) {
                return i;
            }
        }
        return -1;
    }

    // 将字节数组转换为16进制字符串
    public String byteArrayToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            // 过滤掉EF00
            if (b == (byte) 0xEF || b == (byte) 0x00){
                continue;
            }
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    // 将字节数组转换为16进制字符串
    public String byteArrayToHexStringAll(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    public void processRadarData(String data) {
        String head = "55aa55bb";
        String tail = "55cc55dd";

        // 解析上面的数据帧data 包头是head 包尾是tail 从包头到包尾分段取出数据 放入一个字符串列表中 等待解析
        List<String> segments = Lists.newArrayList();
        int headIndex = data.indexOf(head);
        while (headIndex != -1) {
            int tailIndex = data.indexOf(tail, headIndex + head.length());
            if (tailIndex != -1) {
                // 提取从包头到包尾的数据段
                String segment = data.substring(headIndex + head.length(), tailIndex);
                segments.add(segment);
                // 移动到下一个包头的位置
                headIndex = data.indexOf(head, tailIndex + tail.length());
            } else {
                // 没有找到包尾，结束循环
                break;
            }
        }

        // 遍历这些数据帧 解析其中携带的数据
        for (String segment : segments) {
            System.out.println(segment);

            //// 获取数据长度 2字节 4字符 判断数据包长度
            byte[] dataLengthData = extractHexData(segment, 0, 2);
            String dataLengthHexString = byteArrayToHexStringAll(dataLengthData);
            // 将16进制字符串转换为字节数组
            byte[] lengthBytes = new byte[2];
            // 高8位
            lengthBytes[0] = (byte) Integer.parseInt(dataLengthHexString.substring(0, 2), 16);
            // 低8位
            lengthBytes[1] = (byte) Integer.parseInt(dataLengthHexString.substring(2, 4), 16);

            // 将字节数组转换为16位整数，注意网络字节序是大端序
            int byteLength = ((lengthBytes[0] & 0xFF) << 8) | (lengthBytes[1] & 0xFF);
            // 打印结果
            System.out.println("数据长度: " + byteLength);

            // 获取数据帧类型 1字节 2字符 判断是目标轨迹数据还是交通流量数据
            byte[] objectTypeData = extractHexData(segment, 2, 1);
            String objectTypeHexString = byteArrayToHexString(objectTypeData);
            System.out.println("数据帧类型：" + objectTypeHexString);

            // 获取设备编号 20字节 40字符 判断是哪个雷达的发送的数据
            byte[] deviceIdData = extractHexData(segment, 4, 16);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < deviceIdData.length; i++) {
                byte b = deviceIdData[i];
                // 16进制数 "32"
                String hexString = String.format("%02X", b);
                // 将16进制字符串转换为十进制整数
                int decimalValue = Integer.parseInt(hexString, 16);
                // 将十进制整数转换为对应的ASCII字符
                char asciiChar = (char) decimalValue;
                // 如果不为0则添加到字符串中
                if (decimalValue != 0) {
                    builder.append(asciiChar);
                }
            }
            System.out.println("设备编号：" + builder);


            byte[] timestampData = extractHexData(segment, 24, 8);
            String timestampHexString = byteArrayToHexString(timestampData);
            System.out.println("时间戳：" + timestampHexString);
            String localDateTime = getLocalDateTime(segment, timestampData);
            System.out.println("时间戳：" + localDateTime);
            // 获取数据
            // 用获取到的数据长度 减去数据长度(2字节)、数据帧类型(1字节)、校验和(1字节)、数据编号)、时间戳(8字节)、包头包尾(8字节)
            int dataLength = byteLength - 2 - 1 - 1 - 20 - 8;
            segment = segment.substring(64);
            System.out.println("总数据：" + segment);

            // 如果是目标轨迹数据
            if ("01".equals(objectTypeHexString)) {
                if (dataLength >= 36) {
                    byte[] dataBytes = hexStringToByteArray(segment);
                    // 36个字节为一组数据 进行分组解析
                    for (int i = 0; i < dataBytes.length; i += 36) {
                        byte[] dataSegment = Arrays.copyOfRange(dataBytes, i, i + 36);
                        String dataSegmentHexString = byteArrayToHexStringAll(dataSegment);
                        System.out.println("数据：" + dataSegmentHexString);
                        // 获取目标所属车道
                        byte[] targetLaneData = extractHexData(dataSegmentHexString, 2, 1);
                        String targetLaneHexString = byteArrayToHexStringAll(targetLaneData);
                        // 将16进制数转换为10进制数
                        int targetLane = Integer.parseInt(targetLaneHexString, 16);
                        System.out.println("目标所属车道：" + targetLane);
                        // 获取目标类型
                        byte[] carTypeData = extractHexData(dataSegmentHexString, 3, 1);
                        String carTypeHexString = byteArrayToHexStringAll(carTypeData);
                        System.out.println("目标类型：" + carTypeHexString);
                        // 获取目标速度
                        byte[] targetSpeedData = extractHexData(dataSegmentHexString, 20, 2);
                        String targetSpeedHexString = byteArrayToHexStringAll(targetSpeedData);
                        double targetSpeed = Integer.parseInt(targetSpeedHexString, 16) * 0.01;
                        System.out.println("目标速度：" + targetSpeed);
                        // 获取目标经度
                        byte[] targetLongitudeData = extractHexData(dataSegmentHexString, 28, 4);
                        String targetLongitudeHexString = byteArrayToHexStringAll(targetLongitudeData);
                        // 将十六进制字符串转换为long类型的数字
                        long targetLongitudeLongValue = Long.parseLong(targetLongitudeHexString, 16);
                        // 将long类型的数字转换为double类型的数字
                        double targetLongitude = (double) targetLongitudeLongValue / 10000000;
                        System.out.println("目标经度：" + targetLongitude);
                        // 获取目标纬度
                        byte[] targetLatitudeData = extractHexData(dataSegmentHexString, 32, 4);
                        String targetLatitudeHexString = byteArrayToHexStringAll(targetLatitudeData);

                        // 将十六进制字符串转换为long类型的数字
                        long targetLatitudeLongValue = Long.parseLong(targetLatitudeHexString, 16);
                        // 将long类型的数字转换为double类型的数字
                        double targetLatitude = (double) targetLatitudeLongValue / 10000000;
                        System.out.println("目标纬度：" + targetLatitude);
                    }
                }
            }
            // 如果是交通流量数据
            else if ("03".equals(objectTypeHexString)) {
                if (dataLength >= 22) {
                    byte[] dataBytes = hexStringToByteArray(segment);
                    // 22个字节为一组数据 进行分组解析
                    for (int i = 0; i < dataBytes.length; i += 22) {
                        byte[] dataSegment = Arrays.copyOfRange(dataBytes, i, i + 22);
                        String dataSegmentHexString = byteArrayToHexStringAll(dataSegment);
                        System.out.println("数据：" + dataSegmentHexString);
                        // 获取统计周期
                        byte[] statisticsCycleData = extractHexData(dataSegmentHexString, 0, 2);
                        String statisticsCycleHexString = byteArrayToHexStringAll(statisticsCycleData);
                        // 将16进制数转换为10进制数
                        int statisticsCycle = Integer.parseInt(statisticsCycleHexString, 16);
                        System.out.println("统计周期：" + statisticsCycle);
                        // 获取实时车流量
                        byte[] realTimeTrafficFlowData = extractHexData(dataSegmentHexString, 12, 2);
                        String realTimeTrafficFlowHexString = byteArrayToHexStringAll(realTimeTrafficFlowData);
                        // 将16进制数转换为10进制数
                        int realTimeTrafficFlow = Integer.parseInt(realTimeTrafficFlowHexString, 16);
                        System.out.println("总流量：" + realTimeTrafficFlow);
                        // 获取平均车速
                        byte[] averageSpeedData = extractHexData(dataSegmentHexString, 14, 2);
                        String averageSpeedHexString = byteArrayToHexStringAll(averageSpeedData);
                        double averageSpeed = Integer.parseInt(averageSpeedHexString, 16) * 0.1;
                        System.out.println("平均速度：" + averageSpeed);
                        // 获取最大排队长度
                        byte[] maxQueueLengthData = extractHexData(dataSegmentHexString, 20, 2);
                        String maxQueueLengthHexString = byteArrayToHexStringAll(maxQueueLengthData);
                        // 将16进制数转换为10进制数
                        int maxQueueLength = Integer.parseInt(maxQueueLengthHexString, 16);
                        System.out.println("最大排队长度：" + maxQueueLength);
                    }
                }
            }
        }
    }

    public List<RadarDataVO> getRadarDataList(String data) {

        List<RadarDataVO> vos = Lists.newArrayList();

        String head = "55aa55bb";
        String tail = "55cc55dd";

        // 解析上面的数据帧data 包头是head 包尾是tail 从包头到包尾分段取出数据 放入一个字符串列表中 等待解析
        List<String> segments = Lists.newArrayList();
        int headIndex = data.indexOf(head);
        while (headIndex != -1) {
            int tailIndex = data.indexOf(tail, headIndex + head.length());
            if (tailIndex != -1) {
                // 提取从包头到包尾的数据段
                String segment = data.substring(headIndex + head.length(), tailIndex);
                segments.add(segment);
                // 移动到下一个包头的位置
                headIndex = data.indexOf(head, tailIndex + tail.length());
            } else {
                // 没有找到包尾，结束循环
                break;
            }
        }

        // 遍历这些数据帧 解析其中携带的数据
        for (String segment : segments) {
            RadarDataVO vo = new RadarDataVO();
            //// 获取数据长度 2字节 4字符 判断数据包长度
            byte[] dataLengthData = extractHexData(segment, 0, 2);
            String dataLengthHexString = byteArrayToHexStringAll(dataLengthData);
            // 将16进制字符串转换为字节数组
            byte[] lengthBytes = new byte[2];
            // 高8位
            lengthBytes[0] = (byte) Integer.parseInt(dataLengthHexString.substring(0, 2), 16);
            // 低8位
            lengthBytes[1] = (byte) Integer.parseInt(dataLengthHexString.substring(2, 4), 16);

            // 将字节数组转换为16位整数，注意网络字节序是大端序
            int byteLength = ((lengthBytes[0] & 0xFF) << 8) | (lengthBytes[1] & 0xFF);

            // 获取数据帧类型 1字节 2字符 判断是目标轨迹数据还是交通流量数据
            byte[] objectTypeData = extractHexData(segment, 2, 1);
            String objectTypeHexString = byteArrayToHexString(objectTypeData);

            // 获取设备编号 20字节 40字符 判断是哪个雷达的发送的数据
            byte[] deviceIdData = extractHexData(segment, 4, 16);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < deviceIdData.length; i++) {
                byte b = deviceIdData[i];
                // 16进制数 "32"
                String hexString = String.format("%02X", b);
                // 将16进制字符串转换为十进制整数
                int decimalValue = Integer.parseInt(hexString, 16);
                // 将十进制整数转换为对应的ASCII字符
                char asciiChar = (char) decimalValue;
                // 如果不为0则添加到字符串中
                if (decimalValue != 0) {
                    builder.append(asciiChar);
                }
            }
            vo.setDeviceId(builder.toString());

            byte[] timestampData = extractHexData(segment, 24, 8);
            String timestampHexString = byteArrayToHexString(timestampData);
            System.out.println("时间戳：" + timestampHexString);
            String localDateTime = getLocalDateTime(segment, timestampData);
            vo.setTimeStamp(localDateTime);

            // 获取数据
            // 用获取到的数据长度 减去数据长度(2字节)、数据帧类型(1字节)、校验和(1字节)、数据编号)、时间戳(8字节)、包头包尾(8字节)
            int dataLength = byteLength - 2 - 1 - 1 - 20 - 8;
            segment = segment.substring(64);

            // 如果是目标轨迹数据
            if ("01".equals(objectTypeHexString)) {
                vo.setDataType("1");
                if (dataLength >= 36) {
                    byte[] dataBytes = hexStringToByteArray(segment);
                    // 36个字节为一组数据 进行分组解析
                    for (int i = 0; i < dataBytes.length; i += 36) {
                        byte[] dataSegment = Arrays.copyOfRange(dataBytes, i, i + 36);
                        String dataSegmentHexString = byteArrayToHexStringAll(dataSegment);
                        // 获取目标所属车道
                        byte[] targetLaneData = extractHexData(dataSegmentHexString, 2, 1);
                        String targetLaneHexString = byteArrayToHexStringAll(targetLaneData);
                        // 将16进制数转换为10进制数
                        int targetLane = Integer.parseInt(targetLaneHexString, 16);
                        vo.setTargetLane(String.valueOf(targetLane));
                        // 获取目标类型
                        byte[] carTypeData = extractHexData(dataSegmentHexString, 3, 1);
                        String carTypeHexString = byteArrayToHexStringAll(carTypeData);
                        vo.setCarType(carTypeHexString);
                        // 获取目标速度
                        byte[] targetSpeedData = extractHexData(dataSegmentHexString, 20, 2);
                        String targetSpeedHexString = byteArrayToHexStringAll(targetSpeedData);
                        double targetSpeed = Integer.parseInt(targetSpeedHexString, 16) * 0.01;
                        vo.setTargetSpeed(String.valueOf(targetSpeed));
                        // 获取目标经度
                        byte[] targetLongitudeData = extractHexData(dataSegmentHexString, 28, 4);
                        String targetLongitudeHexString = byteArrayToHexStringAll(targetLongitudeData);
                        // 将十六进制字符串转换为long类型的数字
                        long targetLongitudeLongValue = Long.parseLong(targetLongitudeHexString, 16);
                        // 将long类型的数字转换为double类型的数字
                        double targetLongitude = (double) targetLongitudeLongValue / 10000000;
                        vo.setTargetLongitude(String.valueOf(targetLongitude));
                        // 获取目标纬度
                        byte[] targetLatitudeData = extractHexData(dataSegmentHexString, 32, 4);
                        String targetLatitudeHexString = byteArrayToHexStringAll(targetLatitudeData);
                        // 将十六进制字符串转换为long类型的数字
                        long targetLatitudeLongValue = Long.parseLong(targetLatitudeHexString, 16);
                        // 将long类型的数字转换为double类型的数字
                        double targetLatitude = (double) targetLatitudeLongValue / 10000000;
                        vo.setTargetLatitude(String.valueOf(targetLatitude));
                        vos.add(vo);
                    }
                }
            }
            // 如果是交通流量数据
            else if ("03".equals(objectTypeHexString)) {
                vo.setDataType("3");
                if (dataLength >= 22) {
                    byte[] dataBytes = hexStringToByteArray(segment);
                    // 22个字节为一组数据 进行分组解析
                    for (int i = 0; i < dataBytes.length; i += 22) {
                        byte[] dataSegment = Arrays.copyOfRange(dataBytes, i, i + 22);
                        String dataSegmentHexString = byteArrayToHexStringAll(dataSegment);
                        // 获取实时车流量
                        byte[] realTimeTrafficFlowData = extractHexData(dataSegmentHexString, 12, 2);
                        String realTimeTrafficFlowHexString = byteArrayToHexStringAll(realTimeTrafficFlowData);
                        // 将16进制数转换为10进制数
                        int realTimeTrafficFlow = Integer.parseInt(realTimeTrafficFlowHexString, 16);
                        vo.setRealTimeTrafficFlow(String.valueOf(realTimeTrafficFlow));
                        // 获取平均车速
                        byte[] averageSpeedData = extractHexData(dataSegmentHexString, 14, 2);
                        String averageSpeedHexString = byteArrayToHexStringAll(averageSpeedData);
                        double averageSpeed = Integer.parseInt(averageSpeedHexString, 16) * 0.1;
                        vo.setAverageCarSpeed(String.valueOf(averageSpeed));
                        // 获取最大排队长度
                        byte[] maxQueueLengthData = extractHexData(dataSegmentHexString, 20, 2);
                        String maxQueueLengthHexString = byteArrayToHexStringAll(maxQueueLengthData);
                        // 将16进制数转换为10进制数
                        int maxQueueLength = Integer.parseInt(maxQueueLengthHexString, 16);
                        vo.setMaxQueueLength(String.valueOf(maxQueueLength));
                        vos.add(vo);
                    }
                }
            }
        }
        return vos;
    }

    private String getLocalDateTime(String segment, byte[] timestampData) {
        // 第一个字节 -> year
        byte year = timestampData[0];
        // 将16进制字节转换为整数
        int yearInt = Integer.parseInt(String.format("%02X", year), 16);
        // 创建位掩码来提取第0到7位
        int yearMask = 0xFF;
        // 使用位掩码提取第0到第7位
        int extractedYearBits = yearInt & yearMask;
        // 数据 0~255 对应 2000~2255 year 获取实际的年份
        int yearValue = extractedYearBits + 2000;
        System.out.println("年份：" + yearValue);

        // 第二个字节 -> month
        byte month = timestampData[1];
        // 将16进制字节转换为整数
        int monthInt = Integer.parseInt(String.format("%02X", month), 16);
        // 创建位掩码来提取第0到3位
        // 1~12 对应 1~12 month
        int monthMask = 0x0F;
        // 使用位掩码提取第0到第3位
        int monthValue = monthInt & monthMask;
        System.out.println("月份：" + monthValue);

        // 第三个字节 -> day
        byte day = timestampData[2];
        // 将16进制字节转换为整数
        int dayInt = Integer.parseInt(String.format("%02X", day), 16);
        // 创建位掩码来提取第0到4位
        // 数据 1~31 对应 1~31 day
        int dayMask = 0x1F;
        // 使用位掩码提取第0到第4位
        // 数据 1~31 对应 1~31 day
        int dayValue = dayInt & dayMask;
        System.out.println("天：" + dayValue);

        // 第四个字节 -> hour
        byte hour = timestampData[3];
        // 将16进制字节转换为整数
        int hourInt = Integer.parseInt(String.format("%02X", hour), 16);
        // 创建位掩码来提取第0到4位
        int hourMask = 0x1F;
        // 使用位掩码提取第0到第4位
        // 数据 0~31 对应 0~23 hour
        int hourValue = hourInt & hourMask;
        System.out.println("小时：" + hourValue);

        // 第五个字节 -> minute
        byte minute = timestampData[4];
        // 将16进制字节转换为整数
        int minuteInt = Integer.parseInt(String.format("%02X", minute), 16);
        // 创建位掩码来提取第0到5位
        int minuteMask = 0x3F;
        // 使用位掩码提取第0到第5位
        // 数据 0~63 对应 0~59 minute
        int minuteValue = minuteInt & minuteMask;
        System.out.println("分钟：" + minuteValue);

        // 第六个字节 -> second
        byte second = timestampData[5];
        // 将16进制字节转换为整数
        int secondInt = Integer.parseInt(String.format("%02X", second), 16);
        // 创建位掩码来提取第0到5位
        int secondMask = 0x3F;
        // 使用位掩码提取第0到第5位
        // 数据 0~63 对应 0~59 second
        int secondValue = secondInt & secondMask;
        System.out.println("秒：" + secondValue);
        // 第7、8个字节-> millisecond
        // 把第7和第8个字节拼接成16进制字符串 再转换为整数
        byte[] millisecondData = extractHexData(segment, 30, 2);
        String millisecondHexString = byteArrayToHexString(millisecondData);
        if (!StrPool.EMPTY.equals(millisecondHexString)) {
            int millisecondValue = Integer.parseInt(millisecondHexString, 16);
            // 创建位掩码来提取第0到9位
            int millisecondMask = 0x3FF;
            // 使用位掩码提取第0到第9位
            millisecondValue = millisecondValue & millisecondMask;
            // 数据 0~999 对应 0~999 毫秒
            System.out.println("毫秒：" + millisecondValue);
        }
        // 拼接成LocalDateTime 类型的数据
        String localDateTime =  yearValue + "-" + monthValue + "-" + dayValue + " " + hourValue + ":" + minuteValue + ":" + secondValue;
        return localDateTime;
    }
}
