package com.yztiot.streetlamp;

import android.serialport.SerialPort;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class SerialHandle implements Runnable {
    private static final String TAG = "串口处理类";
    private String path = "";//串口地址
    private SerialPort mSerialPort;//串口对象
    private InputStream mInputStream;//串口的输入流对象
    private BufferedInputStream mBuffInputStream;//用于监听硬件返回的信息
    private OutputStream mOutputStream;//串口的输出流对象 用于发送指令
    private SerialInter serialInter;//串口回调接口
    private ScheduledFuture readTask;//串口读取任务

    /**
     * 添加串口回调
     *
     * @param serialInter
     */
    public void addSerialInter(SerialInter serialInter) {
        this.serialInter = serialInter;
    }


    /**
     * 打开串口
     *
     * @param devicePath 串口地址
     * @param baudrate   波特率
     * @param dataBits   数据位
     * @param stopBits   停止位
     * @param parity     校验位
     * @param isRead     是否持续监听串口返回的数据
     * @return 是否打开成功
     */
    public boolean open(String devicePath, int baudrate, int dataBits, int stopBits, int parity, boolean isRead) {
        boolean isSucc = false;
        try {
            if (mSerialPort != null) close();
            File device = new File(devicePath);
            mSerialPort = SerialPort
                    .newBuilder(device, baudrate)
                    .dataBits(dataBits)
                    .stopBits(stopBits)
                    .parity(parity)
                    .build();
            mInputStream = mSerialPort.getInputStream();
            mBuffInputStream = new BufferedInputStream(mInputStream);
            mOutputStream = mSerialPort.getOutputStream();
            isSucc = true;
            path = devicePath;
            Log.d("SerialHandle", "Serial port opened successfully: " + devicePath);
            if (isRead) readData();
        } catch (Throwable tr) {
            Log.e("SerialHandle", "Failed to open serial port: " + tr.getMessage());
            close();
            isSucc = false;
        } finally {
            return isSucc;
        }
    }

    // 读取数据
    private void readData() {
        if (readTask != null) {
            readTask.cancel(true);
            try {
                Thread.sleep(160);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //此处睡眠：当取消任务时 线程池已经执行任务，无法取消，所以等待线程池的任务执行完毕
            readTask = null;
        }
        readTask = SerialManage
                .getInstance()
                .getScheduledExecutor()//获取线程池
                .scheduleAtFixedRate(this, 0, 150, TimeUnit.MILLISECONDS);//执行一个循环任务
    }

    @Override
    public void run() {
        if (Thread.currentThread().isInterrupted()) return;
        try {
            int available = mBuffInputStream.available();
            if (available == 0) return;

            byte[] received = new byte[1024];
            int size = mBuffInputStream.read(received);  // 读取串口数据

            if (size > 0 && serialInter != null) {
                // 将字节数组转换为字符串
                String receivedText = new String(received, 0, size);  // 只转换有效数据部分
                StringBuilder hexString = new StringBuilder();
                for (int i = 0; i < size; i++) {
                    hexString.append(String.format("%02X ", received[i]));  // 转换为16进制形式
                }

                // 打印接收到的数据
//                Log.d("SerialHandle", "Received as String: " + receivedText);  // 打印字符串
                Log.d("SerialHandle", "Received as Hex: " + hexString.toString().trim());  // 打印16进制字符串

                serialInter.readData(path, received, size);  // 回调接收到的数据
            }
        } catch (IOException e) {
            Log.e(TAG, "串口读取数据异常:" + e.toString());
        }
    }

    /**
     * 关闭串口
     */
    public void close() {
        try {
            if (readTask != null && !readTask.isCancelled()) {
                readTask.cancel(true);  // 停止串口读取任务
            }
            if (mInputStream != null) {
                mInputStream.close();  // 关闭输入流
                mInputStream = null;  // 将流置为 null
            }
        } catch (Exception e) {
            Log.e(TAG,"串口输入流对象关闭异常：" + e.toString());
        }

        try {
            if (mOutputStream != null) {
                mOutputStream.close();  // 关闭输出流
                mOutputStream = null;   // 将流置为 null
            }
        } catch (Exception e) {
            Log.e(TAG,"串口输出流对象关闭异常：" + e.toString());
        }

        try {
            if (mSerialPort != null) {
                mSerialPort.close();  // 关闭串口
                mSerialPort = null;   // 将串口对象置为 null
            }
        } catch (Exception e) {
            Log.e(TAG,"串口对象关闭异常：" + e.toString());
        }
    }

    /**
     * 向串口发送指令
     */
    public void send(final String msg) {
        Log.d("SerialHandle", "Sending message: " + msg);
        // 将十六进制字符串转换为字节数组
        byte[] bytes = hexStringToByteArray(msg);
        try {
            if (mOutputStream != null) {
                mOutputStream.write(bytes);  // 通过输出流发送数据
                mOutputStream.flush();      // 确保数据立即发送
            } else {
                Log.e("SerialHandle", "OutputStream is null, unable to send data.");
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("SerialHandle", "Error sending data: " + e.getMessage());
        }
    }
    private byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
}
