package com.unibuy.smartdevice.tools;

import android.content.Context;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.util.Log;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;

public class SimpleCashAcceptorHandler {

    // 使用你找到的 VID 和 PID
    private static final int VENDOR_ID = 0x067B;
    private static final int VENDOR_ID2 = 6790;
    private static final int PRODUCT_ID = 0x23A3;
    private static final int PRODUCT_ID2 = 29987;

    private Context context;
    private UsbManager usbManager;
    private UsbDevice device;
    private UsbDeviceConnection connection;
    private UsbEndpoint inEndpoint;
    private UsbEndpoint outEndpoint;
    private AtomicBoolean isReading = new AtomicBoolean(false);
    private Thread readThread;

    // 這裡要新增一個成員變數來儲存傳入的監聽器
    private MdbEventListener eventListener;


    // **修改後的建構子**
    public SimpleCashAcceptorHandler(Context context, MdbEventListener listener) {
        this.context = context;
        this.usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        this.eventListener = listener; // 將傳入的監聽器存入成員變數
    }


    // 確保這裡的介面是 public
    public interface MdbEventListener {
        void onEventReceived(String event);
    }

    /**
     * 初始化並連接到 USB 轉 RS-232 轉接器
     *
     * @return 如果連接成功返回 true，否則返回 false
     */
    public String connect() {


        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        StringBuilder allDevicesInfo = new StringBuilder();
        // 1. 尋找指定的 USB 設備
        while (deviceIterator.hasNext()) {

            UsbDevice usbDevice = deviceIterator.next();


            // 記錄所有設備的 VID/PID
            allDevicesInfo.append("Name=")
                    .append(usbDevice.getDeviceName())
                    .append(", VID=")
                    .append(usbDevice.getVendorId())
                    .append(", PID=")
                    .append(usbDevice.getProductId())
                    .append("\n");

            // 注意點 不同轉接版可能不同ID 改這裡
            if ((usbDevice.getVendorId() == VENDOR_ID || usbDevice.getVendorId() == VENDOR_ID2) &&
                    (usbDevice.getProductId() == PRODUCT_ID || usbDevice.getProductId() == PRODUCT_ID2))
            {
                device = usbDevice;
                Log.d("MDB_Handler", "找到MDB轉接器: " + device.getDeviceName());
                break;
            }
        }
        if (device == null) {
            Log.e("MDB_Handler", "找不到指定的MDB轉接器。");
            return "找不到指定的MDB轉接器\n" +
                    "目前找到的所有 USB 裝置:\n" +
                    allDevicesInfo.toString();
        }


        // 2. 第一段程式碼：找出該 USB 設備的介面（Interface）。這就像是先確認房子的哪一個「房間」是我們要去的，例如「通訊室」。
        UsbInterface usbInterface = null;
        for (int i = 0; i < device.getInterfaceCount(); i++) {
            UsbInterface currentInterface = device.getInterface(i);
            // 尋找符合 USB CDC (通訊設備類別) 或其他串列埠協定的接口
            if (currentInterface.getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA || currentInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC) {
                usbInterface = currentInterface;
                break;
            }
        }

        if (usbInterface == null) {
            Log.e("CashAcceptor", "找不到通訊接口。");
            return "找不到資料傳的房間";
        }

//
//        // 3. 第二段程式碼：找出該介面裡面的輸入及輸出傳輸點（Endpoint）。這就像是進入了「通訊室」之後，找到裡面專門用來「講話」和「聽話」的電話機。
        for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
            UsbEndpoint endpoint = usbInterface.getEndpoint(i);
            if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
                    inEndpoint = endpoint;
                } else {
                    outEndpoint = endpoint;
                }
            }
        }
//
        if (inEndpoint == null || outEndpoint == null) {
            Log.e("CashAcceptor", "找不到輸入或輸出的端點。");
            return "找不到輸入或輸出的端點";
        }


        // 4. 打開連接並聲明接口
        connection = usbManager.openDevice(device);
        if (connection == null) {
            Log.e("CashAcceptor", "無法打開設備連接，可能沒有權限。");
            return "無法打開設備連接，可能沒有權限。";
        }

        connection.claimInterface(usbInterface, true);
        Log.d("CashAcceptor", "成功連接到 USB 轉接器！");
        return "成功連接到 USB 轉接器！";


    }

    /**
     * 寫入資料到轉接器
     * @param data 要寫入的位元組陣列
     * @return 寫入的位元組數量
     */
    public int writeData(byte[] data) {
        if (connection != null) {
            return connection.bulkTransfer(outEndpoint, data, data.length, 500);
        }
        return -1;
    }

    /**
     * 從轉接器讀取資料
     * @return 讀取的位元組陣列
     */


    public byte[] readData() throws IOException {
        if (connection != null && inEndpoint != null) {
            // 設定一個足夠大的緩衝區
            byte[] buffer = new byte[256];
            int byteCount = 0;
            int totalBytesRead = 0;

            while (true) {
                // 每次讀取一小塊資料
                byteCount = connection.bulkTransfer(inEndpoint, buffer, totalBytesRead, buffer.length - totalBytesRead, 500);

                if (byteCount > 0) {
                    totalBytesRead += byteCount;
                    // 檢查是否讀取到訊息結尾 (例如: 換行符號 '\n' 或 0x0A)
                    // 這邊的邏輯需要根據你的設備實際回傳來調整，但 '\n' 是常見的
                    if (totalBytesRead > 0 && buffer[totalBytesRead - 1] == (byte)0x0A) {
                        break; // 找到結尾，跳出迴圈
                    }
                } else if (byteCount < 0) {
                    // 如果讀取失敗，拋出異常或返回 null
                    Log.e("MDB_Handler", "讀取資料失敗，回傳碼: " + byteCount);
                    return null;
                }

                // 如果沒有收到任何資料，等待一段時間再試
                if (byteCount == 0 && totalBytesRead == 0) {
                    try {
                        Thread.sleep(50); // 短暫延遲，避免佔用過多CPU
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return null;
                    }
                }

                // 避免無限迴圈，設定一個最大讀取長度
                if (totalBytesRead >= buffer.length) {
                    break;
                }
            }

            if (totalBytesRead > 0) {
                byte[] receivedData = new byte[totalBytesRead];
                System.arraycopy(buffer, 0, receivedData, 0, totalBytesRead);
                return receivedData;
            }
        }
        return null;
    }

    /**
     * 關閉連接 USB
     */
    public void close() {
        if (connection != null) {
            if (device != null && device.getInterfaceCount() > 0) {
                connection.releaseInterface(device.getInterface(0));
            }
            connection.close();
            connection = null;
            Log.d("CashAcceptor", "USB 連接已關閉。");
        }
        stopReading();
    }



    /**
     * 啟動背景讀取服務
     */

    /// 持續監聽回應
    public void startReading() {
        if (readThread != null && readThread.isAlive()) {
            return;
        }
        isReading.set(true);
        readThread = new Thread(() -> {
            while (isReading.get()) {
                try {
                    byte[] response = readData();
                    if (response != null && response.length > 0) {
                        String event = new String(response, "UTF-8").trim();
                        if (eventListener != null) {
                            eventListener.onEventReceived(event);
                        }
                    }
                    Thread.sleep(50); // 短暫延遲
                } catch (Exception e) {
                    Log.e("MDB_Handler", "讀取迴圈錯誤: " + e.getMessage());
                    isReading.set(false);
                }
            }
        });
        readThread.start();
    }

    /**
     * 停止背景讀取服務
     */
    public void stopReading() {
        isReading.set(false);
        if (readThread != null) {
            readThread.interrupt();
        }
    }


}