package com.hboxs.serialport.sbc;

import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;


import com.hboxs.serialport.plc.util.HexadecimalUtil;
import com.hboxs.serialport.sbc.frame.VboxCommand;
import com.hboxs.serialport.sbc.frame.VboxCommandFrame;
import com.hboxs.serialport.sbc.frame.VboxResponseFrame;
import com.quyunshuo.androidbaseframemvvm.common.util.ByteUtils;
import com.quyunshuo.androidbaseframemvvm.common.util.LogUtil;
import com.quyunshuo.androidbaseframemvvm.common.util.XLogUtil;

import org.greenrobot.eventbus.EventBus;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;


/**
 * 串口读取线程
 */
public class VboxSerialPortReadThread extends Thread {

    private static final String TAG = "SerialPortReadThread";
    private BufferedInputStream mInputStream;
    private boolean running;
    private VboxCommandFrame commandFrame;
    private VboxSerialPortSendQueue vboxSerialPortSendQueue;


    private static final byte[] START_FLAG = {0x5B, 0x5B};
    private static final byte[] END_FLAG = {(byte) 0xDD, (byte) 0xDD};
    private static final long TIMEOUT_MS = 1000; // 超时时间1秒
    public void init() {
        timeoutTask = new Runnable() {
            @Override
            public void run() {
                synchronized (receiveBuffer) {
                    if (receiveBuffer.size() > 0) {
                        Log.w("SerialPort", "超时清空缓冲区，残留字节数: " + receiveBuffer.size());
                        receiveBuffer.reset();
                    }
                }
            }
        };
    }
    private final Handler timeoutHandler = new Handler(Looper.getMainLooper());
    private Runnable timeoutTask;
    private final ByteArrayOutputStream receiveBuffer = new ByteArrayOutputStream();
    public VboxSerialPortReadThread(InputStream inputStream) {
        mInputStream = new BufferedInputStream(inputStream);
        vboxSerialPortSendQueue = VboxSerialPortSendQueue.getInstance();
    }


    @Override
    public void run() {
        super.run();
        byte[] received = new byte[1024];
        int size;
        running = true;

        while (running) {
            //开始读数据
            vboxSerialPortSendQueue.startReadListThread();
            try {
                int available = mInputStream.available();
                LogUtil.INSTANCE.d("ceshi 0 ",available);
                if (available > 0) {
                    size = mInputStream.read(received);
                    if (size > 0) {
                        LogUtil.INSTANCE.d("ceshi 111111 ",size);
                        onDataReceive(received, size);
                    }
                } else {
                    // 暂停一点时间，免得一直循环造成CPU占用率过高
                    SystemClock.sleep(50);
                }
            } catch (IOException e) {
                running = false;
            }
        }
    }

    private void onDataReceive(byte[] received, int size) {
        //主动通知也有
        //  1. 293C0000120100 支付成功结果通知
        //  2. 发送设备控制指令
        if (size >= 1) {
            Log.d("backinifo","长度："+size);
            //现在来增加，这个数据究竟是谁。
            commandFrame = vboxSerialPortSendQueue.getCurrentFrame();
            if (commandFrame == null) {
                return;
            }
            vboxSerialPortSendQueue.setReceived();//收到数据了，要停止了。
            synchronized (receiveBuffer) {
                // 将新数据追加到缓冲区
                receiveBuffer.write(received, 0, received.length);
                // 尝试解析缓冲区
                processBuffer();
            }
            // 重置超时计时器
            resetTimeoutTimer();
            // 处理接收到的数据
           /* String s1 = ByteUtil.ByteArrToHex(received, 0, size);
            try {
                sleep(50);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            LogUtil.INSTANCE.d("ceshi 2 ",s1);
            XLogUtil.INSTANCE.d("readData s1:" + s1);

            // 1. 如果字节数组长度是单数，补全为双数
            if (size % 2 != 0) {
                byte[] paddedReceived = new byte[size + 1];
                System.arraycopy(received, 0, paddedReceived, 0, size);
                paddedReceived[size] = 0x00; // 补全一个字节
                received = paddedReceived;
                size = received.length; // 更新 size
            }

            // 2. 将字节数组转换为十六进制字符串
            String hexData = ByteUtil.ByteArrToHex(received, 0, size);
            // 3. 使用循环逐个查找帧
            int startIndex = 0;
            while (startIndex < hexData.length()) {
                // 查找 STX 的位置
                int stxIndex = hexData.indexOf(VboxCommand.STX, startIndex);
                if (stxIndex == -1) {
                    break; // 没有找到 STX，退出循环
                }

                // 查找 ETX 的位置
                int etxIndex = hexData.indexOf(VboxCommand.ETX, stxIndex + VboxCommand.STX.length());
                if (etxIndex == -1) {
                    break; // 没有找到 ETX，退出循环
                }
                // 4. 提取一个完整的帧
                String frame = hexData.substring(stxIndex, etxIndex + VboxCommand.ETX.length());
                // 5. 检查头和尾是否匹配
                if (frame.startsWith(VboxCommand.STX) && frame.endsWith(VboxCommand.ETX)) {
                    // 去掉头和尾的 4 个字符（STX 和 ETX）
                    String finallyData = frame.substring(VboxCommand.STX.length(), frame.length() - VboxCommand.ETX.length());

                    // 6. 创建 VboxResponseFrame 对象并设置数据
                    VboxResponseFrame responseFrame = new VboxResponseFrame();
                    responseFrame.setData(ByteUtil.HexToByteArr(finallyData));
                    // 7. 打印最终数据
                    Log.d(TAG, "finallyData onDataReceive11: " + finallyData);
                    Log.d(TAG, "finallyData onDataReceive12: " + commandFrame);
                    Log.d(TAG, "finallyData onDataReceive13: " + commandFrame.getCmd());

                    // 8. 通过 EventBus 推送数据
                    EventBus.getDefault().post(new VBoxMessage(commandFrame.getCmd(), finallyData));
                }

                // 9. 更新 startIndex，继续查找下一个帧
                startIndex = etxIndex + VboxCommand.ETX.length();
             //   startIndex=hexData.length();
                Log.d(TAG, "startIndex: " +startIndex+"hexData.length():"+hexData.length());
            }*/
        }
    }
    // 解析缓冲区核心逻辑
    private void processBuffer() {
        byte[] bufferData = receiveBuffer.toByteArray();
        int bufferSize = bufferData.length;

        int startIndex = findStartIndex(bufferData);
        if (startIndex == -1) {
            resetBuffer(bufferSize); // 无有效起始符，清理缓冲区
            return;
        }

        int endIndex = findEndIndex(bufferData, startIndex);
        if (endIndex == -1) {
            retainUnprocessedData(startIndex); // 保留未处理数据
            return;
        }

        // 提取完整数据帧（排除起始符和结束符）
        int dataStart = startIndex + START_FLAG.length;
        int dataEnd = endIndex - END_FLAG.length + 1;
        if (dataEnd >= dataStart) {
            byte[] packet = Arrays.copyOfRange(bufferData, dataStart, dataEnd);
            onPacketReceived(packet); // 处理有效数据
        }

        // 保留剩余数据并递归解析
        retainRemainingData(endIndex + 1, bufferSize);
    }
    private void onPacketReceived(byte[] packet) {
        if (packet == null || packet.length == 0) {
            Log.e("SerialPort", "空数据包");
            return;
        }
        // 示例1：将字节数组转为十六进制字符串
        String hexStr =ByteUtil.ByteArrToHex(packet, 0, packet.length);
        EventBus.getDefault().post(new VBoxMessage(commandFrame.getCmd(), hexStr));
        Log.d("SerialPort", commandFrame.getCmd()+"收到有效数据包: " + hexStr);

    }
    // 查找起始符位置
    private int findStartIndex(byte[] bufferData) {
        for (int i = 0; i <= bufferData.length - START_FLAG.length; i++) {
            if (bytesMatch(bufferData, i, START_FLAG)) return i;
        }
        return -1;
    }
    // 重置超时计时器
    private void resetTimeoutTimer() {
        timeoutHandler.removeCallbacks(timeoutTask);
        timeoutHandler.postDelayed(timeoutTask, TIMEOUT_MS);
    }

    // 释放资源（关闭串口时调用）
    public void release() {
        timeoutHandler.removeCallbacks(timeoutTask);
        receiveBuffer.reset();
    }
    // 保留未处理数据（用于未找到结束符时）
    private void retainUnprocessedData(int startIndex) {
        byte[] remaining = Arrays.copyOfRange(
                receiveBuffer.toByteArray(),
                startIndex,
                receiveBuffer.size()
        );
        receiveBuffer.reset();
        receiveBuffer.write(remaining, 0, remaining.length);
    }

    // 保留剩余数据并递归解析
    private void retainRemainingData(int fromIndex, int bufferSize) {
        if (fromIndex < bufferSize) {
            byte[] remaining = Arrays.copyOfRange(
                    receiveBuffer.toByteArray(),
                    fromIndex,
                    bufferSize
            );
            receiveBuffer.reset();
            receiveBuffer.write(remaining, 0, remaining.length);
            processBuffer(); // 递归处理剩余数据
        } else {
            receiveBuffer.reset();
        }
    }
    // 查找结束符位置（从起始符后开始）
    private int findEndIndex(byte[] bufferData, int startIndex) {
        for (int i = startIndex + START_FLAG.length; i <= bufferData.length - END_FLAG.length; i++) {
            if (bytesMatch(bufferData, i, END_FLAG)) return i + END_FLAG.length - 1;
        }
        return -1;
    }
    private void resetBuffer(int bufferSize) {
        if (bufferSize >= START_FLAG.length - 1) {
            // 保留最后 N-1 字节，防止起始符被拆分
            byte[] tail = Arrays.copyOfRange(
                    receiveBuffer.toByteArray(),
                    bufferSize - (START_FLAG.length - 1),
                    bufferSize
            );
            receiveBuffer.reset();
            receiveBuffer.write(tail, 0, tail.length);
        } else {
            receiveBuffer.reset();
        }
    }
    // 字节匹配（处理符号问题）
    private boolean bytesMatch(byte[] source, int start, byte[] target) {
        if (start + target.length > source.length) return false;
        for (int i = 0; i < target.length; i++) {
            if ((source[start + i] & 0xFF) != (target[i] & 0xFF)) return false;
        }
        return true;
    }
    /**
     * 停止读线程
     */
    public void close() {
        try {
            release();
            mInputStream.close();
        } catch (IOException e) {
        } finally {
            running = false;
        }
    }
}
