package com.device.comm.mylibrary;

import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.DeadObjectException;
import android.util.Log;

import androidx.annotation.RequiresApi;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by lvwang2002 on 16/1/23.
 */
public class BleDeviceManager {
    private String TAG = "RN_DEVICE_MANAGER";
    private P_DeviceManager m_deviceMngr;

    private UpdateLoop mUpdateLoop;
    private UpdateLoop mMainUpdateLoop;

    private int mSearchedType;

    private int m_retryCountMax = 3;
    private final BluetoothManager m_btMngr;

    public BluetoothAdapter getBluetoothAdapter() {
        return mBluetoothAdapter;
    }

    private BluetoothAdapter mBluetoothAdapter;
    private BleDeviceListener mDeviceListener;

    public Context getContext() {
        return m_context;
    }

    private Context m_context;
    private boolean mIsScanning = false;

    private BTClassicDeviceManager mClassicDeviceManager = null;

    static BleDeviceManager s_instance = null;

    private boolean mIsStartUpdateDevices = true;

    public static BleDeviceManager get(Context context) {
        if(s_instance != null){
            return s_instance;
        }
        synchronized (BleDeviceManager.class){
            if (s_instance == null) {
                // Utils.enforceMainThread(BleNodeConfig.WRONG_THREAD_MESSAGE);
                s_instance = new BleDeviceManager(context, false);

            }
            return s_instance;
        }
    }

    public BleDeviceManager(Context context, boolean isRunOnMainThread) {
        m_context = context;
        if (isRunOnMainThread) {
            this.mUpdateLoop = UpdateLoop.newMainThreadLoop(mUpdateCallback);
        } else {
            this.mUpdateLoop = UpdateLoop.newAnonThreadLoop(mUpdateCallback);
        }

        this.m_btMngr = (BluetoothManager) m_context.getApplicationContext()
                .getSystemService(Context.BLUETOOTH_SERVICE);
        this.mBluetoothAdapter = m_btMngr.getAdapter();
        this.m_deviceMngr = new P_DeviceManager(this);
        this.mDeviceListener = new BleDeviceListener(this);
        this.mMainUpdateLoop = UpdateLoop
                .newMainThreadLoop(mMainUpdateCallback);

        mClassicDeviceManager = new BTClassicDeviceManager(
                this.mBluetoothAdapter, this, context);
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);

        m_context.registerReceiver(mReceiver, filter);
        m_context.registerReceiver(blueStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));

        initScan();//初始化扫描定时器
        startUpdateDeviceTimer();//初始化队列刷新定时器
    }

    public void showLog(boolean isShow){
//        RNLog.DEBUG = isShow;
    }

    /** 开始定时器  */
    private Timer mDeviceTimer = null;
    private UpdateDeviceListCallback mUpdateDeviceListCallback = null;
    public void setUpdateDeviceListCallback(UpdateDeviceListCallback callback){
        mUpdateDeviceListCallback = callback;
    }
    public synchronized void setIsStartUpdateDevices(boolean isStart){
        mIsStartUpdateDevices = isStart;
    }
    public void startUpdateDeviceTimer(){
        if(mDeviceTimer != null){
            return;
        }

        mDeviceTimer = new Timer();
        mDeviceTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                post(new Runnable() {
                    @Override
                    public void run() {
                        synchronized (this){
                            ArrayList<BleDevice> cloneDevices = (ArrayList<BleDevice>) (m_deviceMngr.getDevices().clone());
                            int length = cloneDevices.size();
                            for (int i = 0; i < length; i++) {
                                BleDevice device = cloneDevices.get(i);
                                long searchTime = device.getDeviceSearchDate();
                                long currentTime = System.currentTimeMillis();
                                if ((currentTime - searchTime) > 20 * 1000 &&
                                        device.getDeviceState() == BleDevice.DeviceConnectState.Discovered) {
                                    //如果超过20秒,则在列表中清空.
                                    m_deviceMngr.remove(device);
                                }
                            }

                            postUpdateDeviceList();

                        }

                    }
                });
            }
        },1000,1000);
    }

    public void postUpdateDeviceList(){
        mUpdateLoop.postDelay(new Runnable() {
            @Override
            public void run() {
                updateDeviceList();
            }
        }, 0);
    }

    synchronized public void updateDeviceList(){
        //Log.i(TAG, "当前数据 size: " + m_deviceMngr.getDevices().size());
        if(!mIsStartUpdateDevices){
            return;
        }

        //告知外部结果
        if (mUpdateDeviceListCallback == null) {
            return;
        }

        ArrayList<BleDevice> devicesList = new ArrayList<>();
        for(int i=0;i<m_deviceMngr.getDevices().size();i++){
            BleDevice device =m_deviceMngr.getDevices().get(i);
            if(device.getMacAddress().equals(ENDeviceConst.DEVICE_TYPE_YASEE_UART_GLUCOSE_MAC)){
                devicesList.add(device);
                continue;
            }

            String deviceName = device.getDeviceName();
            if(deviceName == null){
                continue;
            }
            if(!isSearchedTypeWithDeviceName(deviceName)){
                continue;
            }

            devicesList.add(device);
        }
        mUpdateDeviceListCallback.onUpdateDeviceList(devicesList);
    }


    public interface BTStatusCallback{
        void turnOnBT();
        void turnOffBT();
        void turningOnBT();
    }

    BTStatusCallback mStatusCallback =  null;
    public void setStatusCallback(BTStatusCallback statusCallback){
        mStatusCallback = statusCallback;
    }

    boolean isAllowScan = true;
    boolean mBTPowerOn  = true;
    BroadcastReceiver blueStateBroadcastReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO Auto-generated method stub
            int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
            switch (blueState) {
                case BluetoothAdapter.STATE_OFF:
                    RNLog.i(TAG, "blueState: STATE_OFF");
                    isAllowScan = false;
                    mBTPowerOn = false;

                    getMainUpdateLoop().postDelay(new Runnable() {
                        @Override
                        public void run() {
                            if(mStatusCallback == null){
                                return;
                            }

                            mStatusCallback.turnOffBT();
                        }
                    },0);

                    break;
                case BluetoothAdapter.STATE_TURNING_ON:
                    RNLog.i(TAG, "blueState: STATE_TURNING_ON");
                    getMainUpdateLoop().postDelay(new Runnable() {
                        @Override
                        public void run() {
                            if(mStatusCallback == null){
                                return;
                            }

                            mStatusCallback.turningOnBT();
                        }
                    },0);
                    break;
                case BluetoothAdapter.STATE_ON:
                    RNLog.i(TAG, "blueState: STATE_ON");
                    mBTPowerOn = true;
                    mUpdateLoop.postDelay(new Runnable() {
                        @Override
                        public void run() {
                            if(!mBTPowerOn){
                                Log.i(TAG, "bt turn on failure");
                                return;
                            }

                            isAllowScan = true;
//                            startScan();
                            RNLog.i(TAG, "bt turn on suc");

                        }
                    },300);

//					isAllowScan = true;

                    getMainUpdateLoop().postDelay(new Runnable() {
                        @Override
                        public void run() {
                            if(mStatusCallback == null){
                                return;
                            }

                            mStatusCallback.turnOnBT();
                        }
                    },0);

                    break;
                case BluetoothAdapter.STATE_TURNING_OFF:
                    RNLog.i(TAG, "blueState: STATE_TURNING_OFF");
                    isAllowScan = false;
                    mBTPowerOn = false;
                    disconnectAllDevices();

                    break;
                default:
                    break;
            }
        }
    };

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            if (intent == null) {
                RNLog.d(TAG, "异常");

                return;
            }

            String action = intent.getAction();
            BluetoothDevice nativeDevice = intent
                    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            RNLog.d(TAG, "接收到消息:" + action);
            RNLog.d(TAG, "Native mac:" + nativeDevice.getAddress());
            RNLog.d(TAG, "bond:" + nativeDevice.getBondState());
            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                String deviceName = nativeDevice.getName();
                if(deviceName.startsWith("RBP")){
                    BTClassicDevice device =  (BTClassicDevice) getDevice(nativeDevice.getAddress());
                    if(device == null){
                        RNLog.i(TAG,"没有找到脉搏波配对的设备");
                        return;
                    }

                    device.actionBondStateChanged();
                }else{
                    RNLog.d(TAG, "绑定状态改变");
                    if (nativeDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
                        return;
                    }

                    BleDevice device = m_deviceMngr.get(nativeDevice.getAddress());
                    if (device == null) {
                        RNLog.d(TAG, "获取的设备为空");
                        return;
                    }
                    device.deviceBonded();
                }
            }else if(BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)){

                String deviceName = nativeDevice.getName();
                if(deviceName == null){
                    return;
                }
                if(deviceName.startsWith("RBP")){
                    final BTClassicDevice device =  (BTClassicDevice) getDevice(nativeDevice.getAddress());
                    if(device == null){
                        RNLog.i(TAG,"没有找到脉搏波断开");
                        return;
                    }

                    post(new Runnable() {
                        @Override
                        public void run() {
                            RNLog.i(TAG,"接收到脉搏波断开");
                            device.disconnect();
                        }
                    });
                }else if(deviceName.startsWith("INVS300")){
//                    final BTCSFZReaderDevice device = (BTCSFZReaderDevice)getDevice(nativeDevice.getAddress());
                    BTCSFZReaderDevice device = null;
                    ArrayList<BleDevice> devices = getDevices();
                    for(int i=0;i<devices.size();i++){
                        BleDevice tempDevice = devices.get(i);
                        if(tempDevice.getDeviceName().startsWith("INVS300")){
                            device = (BTCSFZReaderDevice)tempDevice;
                            break;
                        }
                    }

                    if(device == null){
                        RNLog.i(TAG,"没有找到INVS身份证读卡器");
                        return;
                    }

                    final BTCSFZReaderDevice postDevice = device;
                    post(new Runnable() {
                        @Override
                        public void run() {
                            RNLog.i(TAG,"发送INVS断开");
                            postDevice.disconnect();
                        }
                    });
                }

            }
        }
    };

    private UpdateLoop.Callback mUpdateCallback = new UpdateLoop.Callback() {

        public void onUpdate(double timestep_seconds) {
            RNLog.d(TAG, "is on update " + timestep_seconds);
        }
    };

    private UpdateLoop.Callback mMainUpdateCallback = new UpdateLoop.Callback() {

        public void onUpdate(double timestep_seconds) {
            RNLog.d(TAG, "is on update " + timestep_seconds);
        }
    };

    public BleDevice getDevice(final String macAddress) {
        // enforceMainThread();

        final String macAddress_normalized = normalizeMacAddress(macAddress);

        final BleDevice device = m_deviceMngr.get(macAddress_normalized);

        if (device != null)
            return device;

        return null;
    }

    public BleDevice getSerialPortDevice(final String macAddress) {
        final BleDevice device = m_deviceMngr.get(macAddress);
        if (device != null)
            return device;

        return null;
    }

    String normalizeMacAddress(final String macAddress) {
        final String macAddress_normalized = Utils_String
                .normalizeMacAddress(macAddress);

        if (macAddress == macAddress_normalized) {
            return macAddress;
        } else if (macAddress.equals(macAddress_normalized)) {
            return macAddress;
        } else {
            RNLog.d(TAG, "Given mac address " + macAddress
                    + " has been auto-normalized to " + macAddress_normalized);

            return macAddress_normalized;
        }
    }

    public UpdateLoop getUpdateLoop() {
        return mUpdateLoop;
    }

    public UpdateLoop getMainUpdateLoop() {
        return mMainUpdateLoop;
    }

    private Timer mHeartTimer;
    private int mHeartCounter = 0;
    private boolean mBleScanEnable = false;
    DiscoverListener mDiscoverListener;

    public void initScan() {

//        mDiscoverListener = discoverListener;

        if (mClassicDeviceManager != null) {
            mClassicDeviceManager.stopScan();
        }

        mBleScanEnable = true;
        if (mHeartTimer != null) {
            return;
        }


        mHeartTimer = new Timer();

        mHeartTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (mHeartCounter == 0) {
//                    RNLog.i(TAG,"开始扫描");
                    if (mBleScanEnable) {
                        startScan();
                    }
                    mHeartCounter++;
                    return;
                } else if (mHeartCounter == 5) {
//                    RNLog.i(TAG,"停止扫描");
                    if (mBleScanEnable) {
                        stopScan();
                    }
                    mHeartCounter = 0;
                    return;
                }

                mHeartCounter++;
            }
        }, 100,500);

    }

    public BTClassicDeviceManager getBTClassicManager() {
        return mClassicDeviceManager;
    }


    public void disableBleScan() {
        mBleScanEnable = false;
        stopScan();
    }

    public void startScan() {

        mIsScanning = true;
        if (postNeeded()) {
            post(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                        startNativeScan_preLollipop();
                    }else{
                        startNativeScan();
                    }

                }
            });
        } else {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                startNativeScan_preLollipop();
            }else{
                startNativeScan();
            }
        }

    }

    /** 停止扫描 */
    public void stopScan() {
        mIsScanning = false;
        if (postNeeded()) {
            post(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                        stopNativeScan_preLollipop();
                    }else{
                        stopNativeScan();
                    }

                }
            });
        } else {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                stopNativeScan_preLollipop();
            }else{
                stopNativeScan();
            }
        }
    }

    /** 设置监听  */
    public void setDiscoverListener(DiscoverListener listener){
        mDiscoverListener = listener;
    }

    private void stopNativeScan_preLollipop() {
        try {
            mBluetoothAdapter
                    .stopLeScan(mDeviceListener.m_scanCallback_preLollipop);
        } catch (NullPointerException e) {
            // --- DRK > Catching this because of exception thrown one
            // time...only ever seen once, so not very reproducible.
            // java.lang.NullPointerException
            // 07-02 15:04:48.149: E/AndroidRuntime(24389): at
            // android.bluetooth.BluetoothAdapter$GattCallbackWrapper.stopLeScan(BluetoothAdapter.java:1819)
            // 07-02 15:04:48.149: E/AndroidRuntime(24389): at
            // android.bluetooth.BluetoothAdapter.stopLeScan(BluetoothAdapter.java:1722)
            RNLog.d(TAG, e.getStackTrace().toString());
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void stopNativeScan() {
        BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
        if(scanner == null){
            return ;
        }
        RNLog.d(TAG,"stop scan:");
        scanner.stopScan(mDeviceListener.scanCallback);
    }


    /** 指定类型连接 */
    public void setSearchedDeviceType(int searchedType){
        mSearchedType = searchedType;
    }



    /** 判断是否是指定的设备  */
    public synchronized boolean isSearchedTypeWithDeviceName(String deviceName){
        if(mSearchedType == ENDeviceConst.SEARCH_TYPE_ALL){
            return true;
        }else if(mSearchedType == ENDeviceConst.SEARCH_TYPE_BLOOD_GLUCOSE) {
            if(deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_HMD_GLUCOSE) ||
               deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_AIKE_GLUCOSE) ||
                deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_G_GLUCOSE) ||
                deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_BIOLAND_GLUCOSE) ||
                deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_BENE_CHECKER) ||
                deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_ACCU_CHEK)){
                return true;
            }else{
                return false;
            }
        }else if(mSearchedType == ENDeviceConst.SEARCH_TYPE_BLOOD_PRESSURE){
            if(deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_RBP) ||
               deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_CLINK_BP) ||
               deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_DY_BP) ||
               deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_YASEE_BP) ||
               deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_YASEE_JN163_BP)){
                return true;
            }else{
                return false;
            }
        }else if(mSearchedType == ENDeviceConst.SEARCH_TYPE_CHOLESTEROL){
            if(deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_IGATE)){
                return true;
            }else{
                return false;
            }
        }else if(mSearchedType == ENDeviceConst.SEARCH_TYPE_CARD_READER){
            if(deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_CARD_TYPE)){
                return true;
            }else{
                return false;
            }
        }else if(mSearchedType == ENDeviceConst.SEARCH_TYPE_BIO_HERMES) {
            return deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_BIO_HERMES);
        }else if(mSearchedType == ENDeviceConst.SEARCH_TYPE_DYNAMIC_GLUCOSE){
            return deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_DG_TYPE_2)||
                    deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_DYNAMIC_GLUCOSE) ||
                    deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_MQ_DY_GLUCOSE);
        }else if(mSearchedType == ENDeviceConst.SEARCH_TYPE_ALL_GLUCOSE){
            return (deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_AIKE_GLUCOSE) ||
                    deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_HMD_GLUCOSE) ||
                    deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_DYNAMIC_GLUCOSE) ||
                    deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_G_GLUCOSE) ||
                    deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_BIOLAND_GLUCOSE) ||
                    deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_MQ_DY_GLUCOSE));
        }else if(mSearchedType == ENDeviceConst.SEARCH_TYPE_ACID){
            return deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_BENE_CHECKER);
        }

        else{
            return  false;
        }

    }

    public class DiscoverEvent {
        private BleDevice mDevice;
        private boolean mNewlyDiscovered;

        public DiscoverEvent(BleDevice device, boolean newlyDiscovered) {
            mDevice = device;
            mNewlyDiscovered = newlyDiscovered;
        }

        public BleDevice getDevice() {
            return mDevice;
        }

        public boolean isNewlyDiscovered() {
            return mNewlyDiscovered;
        }

    }

    /** 处理各种设备的各种错误 */
    public void uhOh(final BleDevice device, final String error) {
        RNLog.d(TAG, error);
        if(device == null){
            return;
        }
        // 没啥太好的办法,断开重来吧.
        if (postNeeded()) {
            post(new Runnable() {
                @Override
                public void run() {
                    device.disconnect();
                }
            });
        } else {
            device.disconnect();
        }
    }

    /** 从记录数组中删除设备,主要是断开连接的时候的使用 */
    public void removeDevice(final BleDevice device) {
        if (postNeeded()) {
            post(new Runnable() {
                @Override
                public void run() {
                    m_deviceMngr.remove(device);
                }
            });
        } else {
            m_deviceMngr.remove(device);
        }
    }

    /** 对外输入接口 */
    public interface DiscoverListener {
        public void onEvent(DiscoverEvent e);
    }

    /** 是否有指定类型的设备连接 */
    public synchronized boolean hasDeviceConnected(int type){
        boolean isConnected = false;

        ArrayList<BleDevice> devices = getDevices();
        int size = devices.size();
        for(int i=0;i<size;i++){
            BleDevice device = devices.get(i);
            int deviceType = deviceNameToDeviceType(device.getDeviceName());
            if(device.getDeviceState() == BleDevice.DeviceConnectState.Connected &&
                deviceType == type){
                isConnected = true;
                break;
            }
        }

        return  isConnected;
    }

    public synchronized boolean hasDeviceConnecting(int type){
        boolean isConnected = false;

        ArrayList<BleDevice> devices = getDevices();
        int size = devices.size();
        for(int i=0;i<size;i++){
            BleDevice device = devices.get(i);
            int deviceType = deviceNameToDeviceType(device.getDeviceName());
            if(device.getDeviceState() == BleDevice.DeviceConnectState.Connecting &&
                deviceType == type){
                isConnected = true;
                break;
            }
        }

        return  isConnected;
    }

    /** 当前连接的设备,如果没有的话,返回null */
    public synchronized BleDevice getCurrentConnectedDeviceWithType(int type){
        BleDevice myDevice = null;
        ArrayList<BleDevice> devices = getDevices();
        int size = devices.size();

        for(int i=0;i<size;i++){
            BleDevice device = devices.get(i);
            String deviceName = device.getDeviceName();
            if(deviceName == null){
                //用户名为空
                continue;
            }

            int deviceType = deviceNameToDeviceType(device.getDeviceName());
            if(device.getDeviceState() == BleDevice.DeviceConnectState.Connected &&
                deviceType == type){
                myDevice = device;
                break;
            }
        }

        return myDevice;
    }

    private  synchronized int deviceNameToDeviceType(String deviceName){
        if(deviceName.startsWith("Glucose") ||
           deviceName.startsWith("BLE-ENUO") ||
           deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_G_GLUCOSE) ||
           deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_BENE_CHECKER) ||
           deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_ACCU_CHEK)
            ){
            return ENDeviceConst.SEARCH_TYPE_BLOOD_GLUCOSE;
        }else if(deviceName.startsWith("RBP") ||
                 deviceName.startsWith("ClinkBlood") ||
                 deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_DY_BP) ||
                deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_YASEE_BP) ||
                deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_YASEE_JN163_BP)
        ){
            return ENDeviceConst.SEARCH_TYPE_BLOOD_PRESSURE;
        }else if(deviceName.startsWith("iGate")){
            return ENDeviceConst.SEARCH_TYPE_CHOLESTEROL ;
        }else if(deviceName.startsWith("INVS300")){
            return ENDeviceConst.SEARCH_TYPE_CARD_READER;
        }else if(deviceName.startsWith("HbA1c")){
            return ENDeviceConst.SEARCH_TYPE_BIO_HERMES;
        }else if(deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_DG_TYPE_2) ||
                deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_DYNAMIC_GLUCOSE) ||
                deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_MQ_DY_GLUCOSE)){
            return ENDeviceConst.SEARCH_TYPE_DYNAMIC_GLUCOSE;
        }else if(deviceName.startsWith(ENDeviceConst.DEVICE_TYPE_BENE_CHECKER)){
            return ENDeviceConst.SEARCH_TYPE_ACID;
        }

        return ENDeviceConst.SEARCH_TYPE_ALL;
    }

    public interface UpdateDeviceListCallback{
        public void onUpdateDeviceList(ArrayList<BleDevice> devices);
    }

    private boolean/* _Mode */startNativeScan_preLollipop() {
        int retryCount = 0;

        while (retryCount <= m_retryCountMax) {

            boolean success = mBluetoothAdapter
                    .startLeScan(mDeviceListener.m_scanCallback_preLollipop);
            if (success) {
                if (retryCount >= 1) {
                    // --- DRK > Not really an ASSERT case...rather just really
                    // want to know if this can happen
                    // --- so if/when it does I want it to be loud.
                    // --- UPDATE: Yes, this hits...TODO: Now have to determine
                    // if this is my fault or Android's.
                    // --- Error message is
                    // "09-29 16:37:11.622: E/BluetoothAdapter(16286): LE Scan has already started".
                    // --- Calling stopLeScan below "fixes" the issue.
                    // --- UPDATE: Seems like it mostly happens on quick
                    // restarts of the app while developing, so
                    // --- maybe the scan started in the previous app sessions
                    // is still lingering in the new session.
                    // ASSERT(false, "Started Le scan on attempt number " +
                    // retryCount);
                }
//                RNLog.i(TAG, "开启扫描成功");
                break;
            }

            retryCount++;

            if (retryCount <= m_retryCountMax) {
                if (retryCount == 1) {
                    RNLog.d(TAG,
                            "Failed first startLeScan() attempt. Calling stopLeScan() then trying again...");
                    mBluetoothAdapter
                            .stopLeScan(mDeviceListener.m_scanCallback_preLollipop);
                } else {
                    RNLog.d(TAG, "Failed startLeScan() attempt number "
                            + retryCount + ". Trying again...");
                }
            }

        }

        if (retryCount > m_retryCountMax) {
            RNLog.d(TAG, "Pre-Lollipop LeScan totally failed to start!");

            // tryClassicDiscovery(intent, /*suppressUhOh=*/false); 失败了,不知道还想干什么

            // return Mode_CLASSIC;
            return false;
        } else {
            if (retryCount > 0) {
                RNLog.d(TAG, "Started native scan with " + (retryCount + 1)
                        + " attempts.");
            }

            return true;
        }
    }



//    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private boolean/* _Mode */startNativeScan() {
//        RNLog.d(TAG,"start  native scan:");
        BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
        if(scanner == null){
            return false;
        }
//        RNLog.d(TAG,"start scan:");
        scanner.startScan(mDeviceListener.scanCallback);
        return true;
    }

    void  onDiscoveredFromNativeStack(final BluetoothDevice device_native,
                                     final int rssi, final byte[] scanRecord_nullable) {
        // --- DRK > Not sure if queued up messages to library's thread can
        // sneak in a device discovery event
        // --- after user called stopScan(), so just a check to prevent
        // unexpected callbacks to the user.
        synchronized (BleDeviceManager.this) {
            if (!isAllowScan) {
                RNLog.d(TAG, "blue tooth disable");
                return;
            }

//            RNLog.d(TAG, "ble device manger is scanning");
            if (!mIsScanning)
                return;

            final String rawDeviceName;

            try {
                rawDeviceName = device_native.getName();
            }

            // --- DRK > Can occasionally catch a DeadObjectException or
            // NullPointerException here...nothing we can do about it.
            catch (Exception e) {
                RNLog.i(TAG, e.getStackTrace().toString());

                // --- DRK > Can't actually catch the DeadObjectException itself.
                if (e instanceof DeadObjectException) {
                    RNLog.d(TAG, e.getStackTrace().toString());
                } else {
                    RNLog.d(TAG, e.getStackTrace().toString());
                }

                return;
            }

            final String loggedDeviceName = rawDeviceName != null ? rawDeviceName
                    : "<NO_NAME>";
//            RNLog.d(TAG,"Scan Device Name: "+loggedDeviceName);
            List<String> supportDeviceNames = BleDeviceManagerConfigure
                    .getSupportDeviceName();

            if (!isSearchedTypeWithDeviceName(loggedDeviceName)) {
//                RNLog.i("SCAN_", "扫描的不支持类型的设备"+loggedDeviceName);
                return;
            }

            boolean isSupportDevice = false;
            for (String deviceName : supportDeviceNames) {
                if (loggedDeviceName.startsWith(deviceName)) {
                    isSupportDevice = true;
                }
            }

            if (!isSupportDevice) {
                RNLog.i("SCAN_", "扫描到不支持设备");
                return;
            }

            final String macAddress = device_native.getAddress();
            BleDevice device_sweetblue = m_deviceMngr.get(macAddress);

            if (device_sweetblue == null) {
                RNLog.i(TAG, "Discovered device " + loggedDeviceName + " "
                        + macAddress + " not in list.");
            } else {
                if (device_sweetblue.getBluetoothDevice().equals(device_native)) {
                    RNLog.i(TAG, "Discovered device " + loggedDeviceName + " "
                            + macAddress + " already in list.");
                } else {
                    RNLog.i(TAG,
                            "Discovered device "
                                    + loggedDeviceName
                                    + " "
                                    + macAddress
                                    + " already in list but with new native device instance.");
                }
            }

            boolean newlyDiscovered;
            final DiscoverEvent event;
            long currentTime = System.currentTimeMillis();
            if (device_sweetblue == null) {
                newlyDiscovered = true;

                BleDevice bleDevice;
                if(device_native.getName().startsWith("RBP")){
                    bleDevice = new BTClassicDevice(this,device_native);
                }else if(device_native.getName().startsWith("INVS300")){
//                    bleDevice = new BTClassicDevice(this,device_native);
                    bleDevice = new BTCSFZReaderDevice(mBluetoothAdapter,this,device_native);
                }else if(device_native.getName().startsWith(ENDeviceConst.DEVICE_TYPE_BIO_HERMES)){
                    bleDevice = new BTBioHermesDevice(mBluetoothAdapter,this,device_native);
                }else{
                    bleDevice = new BleDevice(this, macAddress);
                }

                m_deviceMngr.add(bleDevice);
                bleDevice.setDeviceDate(currentTime);
                event = new DiscoverEvent(bleDevice, newlyDiscovered);
            } else {
                newlyDiscovered = false;
                device_sweetblue.setDeviceDate(currentTime);
                event = new DiscoverEvent(device_sweetblue, newlyDiscovered);
            }

            mMainUpdateLoop.postDelay(new Runnable() {
                @Override
                public void run() {
                    if (mDiscoverListener == null) {
                        return;
                    }
                    mDiscoverListener.onEvent(event);
                }
            }, 0);
        }
    }

    public ArrayList<BleDevice> getDevices() {
        return m_deviceMngr.getDevices();
    }

    private boolean postNeeded() {
        return getUpdateLoop().postNeeded();
    }

    private void post(final Runnable runnable) {
        final UpdateLoop updateLoop = getUpdateLoop();

        updateLoop.postIfNeeded(runnable);
    }

    public BleDevice addAutoConnectDevice(String mac,String deviceName){
        BleDevice bleDevice = new BleDevice(this,mac,deviceName);
        m_deviceMngr.add(bleDevice);
        return bleDevice;
    }

    public BleDevice addSerialPortDevice(String mac,String deviceName){
        BleDevice bleDevice = new BleDevice(this,mac,deviceName);
        m_deviceMngr.add(bleDevice);
        return bleDevice;
    }

    public BleDevice addAutoConnectDevice(String deviceName){
        Object[] list = this.getBluetoothAdapter()
                    .getBondedDevices().toArray();

        BluetoothDevice bondedDevice = null;
        for(Object device:list){
            BluetoothDevice btDevice = (BluetoothDevice) device;
            if(btDevice.getName().startsWith(deviceName)){
                bondedDevice = btDevice;
                break;
            }
        }

        if(bondedDevice==null){
            return null;
        }


        BleDevice bleDevice = new BleDevice(this,bondedDevice.getAddress(),deviceName);
        m_deviceMngr.add(bleDevice);
        return bleDevice;
    }

    public void enableBleScan() {
        mBleScanEnable = true;
        startScan();
    }


    public void disconnectAllDevices(){
        mMainUpdateLoop.postDelay(new Runnable() {
            @Override
            public void run() {
                RNLog.i(TAG,"断开所有的设备");
                ArrayList<BleDevice> devices = getDevices();
                if(devices.size()<=0){
                    RNLog.i(TAG,"not have device");
                    return;
                }


                for(int i=0;i<devices.size();i++){
                    BleDevice device = devices.get(i);

                    device.forceDisconnect();
                }
            }
        },100);

    }
}


//    public static boolean isOnMainThread()
//    {
//        return Looper.getMainLooper().getThread() == Thread.currentThread();
//    }
//
//    public static void enforceMainThread(final String message)
//    {
//        if( !isOnMainThread() )
//        {
//            throw new WrongThreadError(message);
//        }
//    }
