package cgmblelib.ble.gattcallback;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothProfile;
import android.util.Log;

import androidx.annotation.NonNull;

import java.util.List;
import java.util.concurrent.TimeUnit;

import cgmblelib.Enum.enumError;
import cgmblelib.Enum.enumUnBind;
import cgmblelib.base.BApplication;
import cgmblelib.ble.entity.AlgorithmCallBack;
import cgmblelib.ble.reconnectManagament.ReconnectManagement;
import cgmblelib.custom.livedata.ManagementLiveData;
import cgmblelib.custom.livedata.connect.EnumConnect;
import cgmblelib.database.entity.PocDevice;
import cgmblelib.database.entity.PocGlucose;
import cgmblelib.database.repository.RepositoryDevice;
import cgmblelib.database.repository.RepositoryGlucose;
import cgmblelib.qr.QRInformation;
import cgmblelib.utils.AxisYForGlucoseLevel;
import cgmblelib.utils.ConstantsLibrary;
import cgmblelib.utils.MyLog;
import cgmblelib.utils.SharedPreferencesLibraryUtil;
import cgmblelib.utils.Tool;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import ist.com.sdk.EDevice;
import ist.com.sdk.HexadecimalTools;
import ist.com.sdk.ProtocolTools;
import ist.com.sdk.TransmitterReset;

/**
 * Created by minyuchun on 2019/12/23.
 *
 * @author minyuchun
 */
public class ManageGattCallback implements LineUpTaskGlucoseProcess.OnTaskListener {
  /**
   * 连接超时的时间
   */
  private static final long TIMEOUT_RECONNECT = 20 * 1000;
  /**
   * 每3分钟10秒主动去检查数据,获取数据
   */
  private static final long TIME_DATA_CHECK = ConstantsLibrary.GLUCOSE_DATA_INTERVAL * 60 * 1000 + 10 * 1000;
  /**
   * 10 秒连接超时, 延时70秒同步, 请求下一个数据的任务
   */
  private Disposable mDisposable;

  /**
   * 超时断开
   */
  private Disposable disconnectDisposable;


  /**
   * 延迟拉取数据
   */
  private Disposable delayDisposable;
  /**
   * 通讯协议 接口
   */
  private ProtocolTools mProtocolTools;
  /**
   * 记录数据同步的状态
   */
  private EnumSynchronous DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_END;
  /**
   * 解除绑定的类型
   */
  public enumUnBind unBindType = enumUnBind.NONE;
  /**
   * 数据推送上来后再去pull 血糖数据，用于发射器计算血糖数据
   */
  private boolean pullDataForPush = false;
  private int Number = 40;

  private ManageGattCallback() {
    mProtocolTools = new ProtocolTools();
    LineUpTaskGlucoseProcess.getInstance().setOnTaskListener(this);
  }

  @Override
  public void nextTask(ProtocolTools.Glucose task) {
    //CT2_5 获取大量的血糖值
    test_pull_glucose_series(task);
  }

  @Override
  public void completedTask(boolean isInitiative) {
    MyLog.i("completedTask isInitiative " + isInitiative);
    DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_END;
    if (!isInitiative) {
      //是自动结束的,请求下一个数据
      requestNextGlucoseData();
    } else {
      //同步结束
      ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_PULL_END);
    }
  }

  private static class SingletonInstance {
    private static final ManageGattCallback INSTANCE = new ManageGattCallback();
  }

  public static ManageGattCallback getInstance() {
    return SingletonInstance.INSTANCE;
  }

  /***
   * 蓝牙状态发生变化
   * @param isBluetoothOpen 蓝牙是否开启
   */
  public void bluetoothChange(boolean isBluetoothOpen) {
    if (!isBluetoothOpen) {
      BleGattCallback.getInstance().closeGatt();
    }
  }

  /**
   * 缓存重连
   *
   * @param device 需要重连的发射器
   */
  public void reConnectViaCache(PocDevice device) {
    try {
      BluetoothAdapter adapter = Tool.getBluetoothAdapter(BApplication.getContext());
      MyLog.i("使用缓存连接");
      if (adapter != null && adapter.isEnabled()) {
        BluetoothDevice bluetoothDevice = BleGattCallback.getInstance().checkGattDevice(device);
        if (bluetoothDevice != null) {
          MyLog.i("尝试进行缓存重连");
          if (BleGattCallback.getInstance().connectGatt()) {
            ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_START);
            disConnectTimeout(ReconnectManagement.TIME_INTERVAL_RECONNECT_GATT_TIMEOUT, bluetoothDevice);
          } else {
            MyLog.wLog("GATT连接设备失败,开始新建GATT连接");
            ReconnectManagement.getInstance().reconnect(ReconnectManagement.ReconnectState.STATE_NEW_GATT);
          }
        } else {
          MyLog.wLog("checkGattDevice设备验证失败,开始新建GATT连接");
          ReconnectManagement.getInstance().reconnect(ReconnectManagement.ReconnectState.STATE_NEW_GATT);
        }
      } else {
        MyLog.w("蓝牙关闭,停止进行重连");
        ReconnectManagement.getInstance().stopReconnect();
      }
    } catch (Exception e) {
      e.printStackTrace();
      MyLog.eLog("使用缓存连接 " + e.getMessage());
    }
  }

  /**
   * 新建GATT进行重连
   *
   * @param device 需要连接的设备
   */
  @SuppressLint("MissingPermission")
  public void reConnectViaNew(PocDevice device) {
    try {
      BluetoothAdapter adapter = Tool.getBluetoothAdapter(BApplication.getContext());
      MyLog.i("使用设备连接 ");
      if (adapter != null && adapter.isEnabled()) {
        BluetoothDevice newDevice = adapter.getRemoteDevice(device.getAddress());
        if (newDevice != null) {
          if (connect(newDevice)) {
            MyLog.i("新建蓝牙设备进行连接");
            ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_START);
            disConnectTimeout(ReconnectManagement.TIME_INTERVAL_RECONNECT_GATT_TIMEOUT, newDevice);
          } else {
            MyLog.i("新建GATT连接失败，需要搜索再进行重连");
            ReconnectManagement.getInstance().reconnect(ReconnectManagement.ReconnectState.STATE_SCAN_AUTO);
          }
        } else {
          MyLog.i("新建GATT连接失败，需要搜索再进行重连");
          ReconnectManagement.getInstance().reconnect(ReconnectManagement.ReconnectState.STATE_SCAN_AUTO);
        }
      } else {
        MyLog.w("bluetooth off,stop scan connect");
        ReconnectManagement.getInstance().stopReconnect();
      }
    } catch (Exception e) {
      e.printStackTrace();
      MyLog.i("使用设备连接 " + e.getMessage());
    }
  }

  /**
   * 通过mac地址进行连接
   *
   * @param address mac地址
   */
  @SuppressLint("MissingPermission")
  public void ConnectViaAddress(String address) {
    try {
      if (address == null || BApplication.getContext() == null) {
        return;
      }

      BluetoothAdapter adapter = Tool.getBluetoothAdapter(BApplication.getContext());
      MyLog.i("connect via address ");
      if (adapter != null && adapter.isEnabled()) {
        BluetoothDevice newDevice = adapter.getRemoteDevice(address);
        if (newDevice != null) {
          if (connect(newDevice)) {
            MyLog.i("connect via address success");
            ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_START);
            disConnectTimeout(TIMEOUT_RECONNECT, newDevice);
          } else {
            MyLog.e("connect via address failed");
          }
        } else {
          MyLog.i("connect via address new device failed");
        }
      } else {
        MyLog.w("bluetooth off,stop scan connect");
        ReconnectManagement.getInstance().stopReconnect();
      }
    } catch (Exception e) {
      Log.e("ConnectViaAddress", "ConnectViaAddress: " + e.getMessage());
      e.printStackTrace();
    }
  }

  /**
   * 建立连接
   *
   * @param newDevice 新的需要连接的蓝牙设备
   * @return 是否进行连接
   */
  @SuppressLint("MissingPermission")
  public boolean connect(@NonNull BluetoothDevice newDevice) {
    BluetoothGatt gatt = BleGattCallback.getInstance().connectDevice(BApplication.getContext(), newDevice);
    return gatt != null && gatt.getDevice() != null && gatt.getDevice().getName() != null && gatt.getDevice().getAddress() != null;
  }

  /**
   * 释放Gatt资源
   */
  public void removeHandler() {
    dispose();
    BleGattCallback.getInstance().closeGatt();
  }

  /**
   * 成功建立连接调用的方法,当gatt.close后不会回调此方法
   *
   * @param eDevice  发射器类型
   * @param gatt     gatt
   * @param status   连接是否成功
   * @param newState 连接是否成功
   */
  @SuppressLint("MissingPermission")
  public void onConnectionStateChange(EDevice eDevice, BluetoothGatt gatt, int status, int newState) {
    MyLog.i("onConnectionStateChange status = " + status + ",newState = " + newState);
    if (newState == BluetoothProfile.STATE_CONNECTED) {
      //连接成功后,将同步流程的标识重置
      DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_END;
      gatt.requestMtu(480);
    } else {
      PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
      if (device != null && device.isBound()) {
        if (device.isConnect()) {
          dispose();
          //发现发射器处于连接状态，设置为断开连接
          boolean isSuccess = RepositoryDevice.getInstance(BApplication.getContext()).connectIoThread(device, false);
        } else {
          if (status == 133) {
            ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_FAIL_133);
          } else if (status == BluetoothGatt.GATT_FAILURE) {
            ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_FAIL_257);
          } else {
            ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_DISCONNECT);
          }
          //发现设备没有连接，清除通知
          ReconnectManagement.getInstance().reconnect(ReconnectManagement.ReconnectState.STATE_CONNECTION_DELAY);
        }
      } else {
        ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_BIND_FAIL);
      }
    }
  }


  public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
    MyLog.eLog("onMtuChanged " + mtu);
    Number = (mtu - 7) / 6 - 1;
    if (Number > 40) {
      Number = 40;
    }
    //连接成功后,获取服务
    MyLog.i("发现服务 " + BleGattCallback.getInstance().discoverServices());
  }

  /**
   * 发现服务
   *
   * @param eDevice 发射器类型
   * @param gatt    gatt
   * @param status  是否成功
   */
  public void onServicesDiscovered(EDevice eDevice, BluetoothGatt gatt, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
      MyLog.d("onServicesDiscovered success ");
      if (!BleGattCallback.getInstance().setCharacteristicNotification()) {
        dispose();
      }
    } else {
      MyLog.w("onServicesDiscovered error " + status);
      ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_DISCONNECT);
      removeHandler();
    }
  }

  /***
   * 特征写入成功
   * @param eDevice 发射器类型
   * @param gatt gatt
   * @param descriptor 特征
   * @param status 状态
   */
  public void onDescriptorWrite(EDevice eDevice, BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
      MyLog.d("onDescriptorWrite success ");
      PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
      if (device != null && device.isBound()) {
        //没收到发射器的0x0a的信号导致周期结束提示解绑失效
        PocGlucose glucose = RepositoryGlucose.getInstance(BApplication.getContext()).getLatestGlucoseByDeviceIdIoThread(device.getId());
        if (glucose != null && glucose.getGlucoseId() > eDevice.getEndNumber() - 1) {
          GattTool.unBindInDatabaseIoThread(BApplication.getContext(), device, enumUnBind.UNBIND_COMMAND);
          removeHandler();
        } else {
          //CT2.5 获取发射器是否重置
          BleGattCallback.getInstance().writeCharacteristic(mProtocolTools.reset_request(eDevice));
        }
      } else {
        MyLog.i("直接判断其传感器是否匹配");
        SharedPreferencesLibraryUtil sharedPreferencesLibraryUtil = new SharedPreferencesLibraryUtil(BApplication.getContext());
        QRInformation information = sharedPreferencesLibraryUtil.getQRInformation();
        if (information != null) {
          MyLog.i("发送电量检测命令");
          BleGattCallback.getInstance().writeCharacteristic(mProtocolTools.check_request(eDevice), 2, 100, 2500);
        } else {
          MyLog.i(" 无二维码或者二维码不适用");
          ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_MISMATCHED_SENSOR_TRANSMITTER);
          removeHandler();
        }

      }
    } else {
      ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_DISCONNECT);
      removeHandler();
    }
  }

  /**
   * 设置数据库为连接的状态
   *
   * @param gatt   通道
   * @param device 设备数据
   */
  private void setDeviceInDatabaseConnect(BluetoothGatt gatt, PocDevice device) {
    if (GattTool.isGattConnect(gatt.getDevice())) {
      //设备已经绑定过
      boolean isSuccess = RepositoryDevice.getInstance(BApplication.getContext()).connectIoThread(device, true);
      MyLog.i("set device in database connect " + isSuccess);
      if (isSuccess) {
        dispose();
        ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_SUCCESS);
        requestNextGlucoseData(device);
      } else {
        BleGattCallback.getInstance().disConnectGatt();
      }
    } else {
      //添加补充 -- 断开连接的提示
      ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_DISCONNECT);
      removeHandler();
    }
  }

  /**
   * 接收器 - > 传感器
   *
   * @param gatt           gatt
   * @param characteristic 写入的数据
   * @param status         是否连接成功
   */
  public void onCharacteristicWrite(EDevice eDevice, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
      switch (GattTool.getFirstByte(characteristic.getValue())) {
        case 0x01:
          MyLog.d("ct3_version_request success");
          break;
        case 0x09:
          MyLog.i("0x09 success " + HexadecimalTools.ByteArrayToStrs16(characteristic.getValue()));
          break;
        case 0x0C:
        case 0x0D:
        case 0x22:
          MyLog.i("ct3_getData success or CT2.5");
          if (DATA_SYNCHRONIZATIONS == EnumSynchronous.SYNCHRONOUS_READY) {
            DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_WRITE;
          }
          break;
        case 0x0A:
          MyLog.d("ct3_unBind_request success");
          break;
        case 0x08:
          MyLog.d("ct3_pull_request success");
          if (DATA_SYNCHRONIZATIONS == EnumSynchronous.SYNCHRONOUS_READY) {
            DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_WRITE;
          }
          break;
        //---ct2.5/ct3蓝牙部分
        case 0x11:
          MyLog.d("ct2.5_reset_request success");
          break;
        case 0x05:
          MyLog.d("ct3_check_request success ");
          break;
        case 0x0B:
          MyLog.i("ct3_setK_setR success");
          break;
        case 0x03:
          MyLog.d("test_setData_request success");
          break;
        case 0x06:
          MyLog.d("ct3_init_request success");
          break;
        case 0x0F:
          MyLog.d("ct3_low_power success " + HexadecimalTools.ByteArrayToStrs16(characteristic.getValue()));
          break;
        default:
          break;
      }
    }
  }

  /**
   * 传感器 - > 接收器
   *
   * @param gatt  gatt
   * @param bytes 数据
   */
  public void onCharacteristicChanged(EDevice eDevice, BluetoothGatt gatt, @NonNull byte start, @NonNull byte[] bytes) {
    switch (start) {
      case 0x01:
        MyLog.i("0x01 = " + HexadecimalTools.ByteArrayToStrs16(bytes));
        break;
      case 0x0C:
      case 0x0D:
      case 0x22:
        test_pull_glucose_se(eDevice, gatt, bytes);
        break;
      case 0x0A:
        test_unBind_response(eDevice, gatt, bytes);
        break;
      case 0x11:
        reset_response(gatt, eDevice, bytes);
        break;
      case 0x05:
        test_check_response(eDevice, gatt, bytes);
        break;
      case 0x03:
      case 0x04:
        test_setDate_response(eDevice, gatt, bytes);
        break;
      case 0x06:
        test_init_response(eDevice, gatt, bytes);
        break;
      case 0x0F:
        test_lowPower_response(eDevice, bytes);
        break;
      case 0x07:
        test_push_glucose(eDevice, gatt, bytes);
        break;
      case 0x08:
        test_pull_glucose(eDevice, gatt, bytes);
        break;
      default:
        break;
    }
  }

  /**
   * 设置初始化时间或者获取时间，设备绑定时获取时间否则设置初始化时间
   *
   * @param bytes 数据
   */
  private void test_lowPower_response(EDevice eDevice, byte[] bytes) {
    //设置时间
    if (mProtocolTools.lowPower_response(bytes, eDevice)) {
      MyLog.d("lowPower_response success");
    }
  }

  /**
   * 日期设置回调
   *
   * @param gatt  gatt
   * @param bytes 数据
   */
  private void test_setDate_response(EDevice eDevice, BluetoothGatt gatt, byte[] bytes) {
    if (mProtocolTools.setDate_response(bytes, eDevice)) {
      MyLog.d("test_setDate_response " + HexadecimalTools.ByteArrayToStrs16(bytes));
      //初始化
      BleGattCallback.getInstance().writeCharacteristic(mProtocolTools.init_request(eDevice));
    } else {
      MyLog.w("setDate_response error");
      ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_DISCONNECT);
      removeHandler();
    }
  }

  private void test_check_response(EDevice eDevice, BluetoothGatt gatt, byte[] bytes) {
    MyLog.wLog("test_check_response " + HexadecimalTools.ByteArrayToStrs16(bytes));
    int checkResponse = ConstantsLibrary.IS_TEST ? mProtocolTools.check_response_test(bytes, eDevice) : mProtocolTools.check_response(bytes, eDevice);
    if (checkResponse == ProtocolTools.SUCCESS) {
      BleGattCallback.getInstance().writeCharacteristic(mProtocolTools.setDate_request(eDevice));
    } else {
      if (checkResponse == ProtocolTools.CHECK_FAIL_POWER) {
        ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_BIND_CHECK_LOW_POWER);
      } else if (checkResponse == ProtocolTools.CHECK_FAIL_TEMPERATURE) {
        ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_BIND_CHECK_ERROR_TEMPERATURE);
      }
      removeHandler();
    }
  }

  /**
   * ct2 ct3初始化回调
   *
   * @param eDevice 发射器类型
   * @param gatt    gatt
   * @param bytes   数据
   */
  @SuppressLint("MissingPermission")
  private void test_init_response(EDevice eDevice, BluetoothGatt gatt, byte[] bytes) {
    MyLog.d("ct3_init_response ");
    PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
    if (device != null && device.isBound()) {
      MyLog.iLog("绑定状态回复初始化成功");
    } else {
      long deviceId = RepositoryDevice.getInstance(BApplication.getContext()).insertDeviceIoThread(gatt.getDevice().getAddress(), gatt.getDevice().getName());
      if (deviceId > 0) {
        if (eDevice != null) {
          AxisYForGlucoseLevel.getInstance().setGattMessage(eDevice.geteGattMessage());
        }
        ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_BIND_SUCCESS);
        MyLog.setLocalLog(deviceId, gatt.getDevice().getName());
        BleGattCallback.getInstance().writeCharacteristic(mProtocolTools.lowPower_request(eDevice));
        pullDataDelay();
      } else {
        ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_DISCONNECT);
        removeHandler();
      }
    }
  }

  /**
   * 数据自动上传
   *
   * @param gatt  gatt
   * @param bytes 数据
   */
  private synchronized void test_push_glucose(EDevice eDevice, BluetoothGatt gatt, byte[] bytes) {
    MyLog.i("上传数据 " + HexadecimalTools.ByteArrayToStrs16(bytes));
    if (DATA_SYNCHRONIZATIONS == EnumSynchronous.SYNCHRONOUS_END) {
      MyLog.d("test_push_response");
      //有时候会出现发射器不向接收器上传data的问题
      ProtocolTools.Glucose glucose = mProtocolTools.getGlucose(bytes, eDevice);
      if (glucose != null) {
        dispose();
        String info = glucose.getId() + "ele:" + glucose.getElectric();
        PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
        PocGlucose pocGlucose = GattTool.getPocGlucose(glucose, device, bytes, eDevice);
        if (pocGlucose != null) {
          AlgorithmCallBack callBack = GattTool.algorithm(BApplication.getContext(), pocGlucose, device);
          handleNewGlucose(callBack, device);
          if (ConstantsLibrary.IS_PULL_ALL_CURRENT_AFTER_PUSH_CT3) {
            //是否同步所有的电流,同步左右电流就发信息
            BleGattCallback.getInstance().writeCharacteristic(new byte[]{0x12});
          }
        } else {
          requestNextGlucoseData(device);
        }
      } else {
        BleGattCallback.getInstance().disConnectGatt();
      }
    } else {
      MyLog.w("处于同步数据的流程,请稍等 " + DATA_SYNCHRONIZATIONS);
    }
  }

  /**
   * 批量同步数据
   *
   * @param eDevice 设备信息
   * @param gatt    gatt
   * @param bytes   数据
   */
  private synchronized void test_pull_glucose_se(EDevice eDevice, BluetoothGatt gatt, byte[] bytes) {
    MyLog.i("0x22 receive:" + HexadecimalTools.ByteArrayToStrs16(bytes));
    List<ProtocolTools.Glucose> glucoseList = mProtocolTools.getGlucose_series(bytes, eDevice);
    if (glucoseList != null && glucoseList.size() > 0) {
      LineUpTaskGlucoseProcess.getInstance().addTasks(glucoseList);
    } else {
      //低功耗
      DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_END;
      ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_PULL_END);
      pullDataDelay();
      BleGattCallback.getInstance().writeCharacteristic(mProtocolTools.lowPower_request(eDevice));
    }
  }

  /**
   * 同步数据
   *
   * @param gatt  gatt
   * @param bytes 数据
   */
  private synchronized void test_pull_glucose(EDevice eDevice, BluetoothGatt gatt, byte[] bytes) {
    MyLog.d("pull_response success_test " + HexadecimalTools.ByteArrayToStrs16(bytes));
    DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_READ;
    ProtocolTools.Glucose glucose = mProtocolTools.getGlucose(bytes, eDevice);
    if (glucose != null) {
      dispose();
      PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
      int peak = 256;
      if (glucose.getIw() >= peak || glucose.getIb() > peak) {
        DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_END;
        ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_PULL_END);
        pullDataDelay();
        BleGattCallback.getInstance().writeCharacteristic(mProtocolTools.lowPower_request(eDevice));
      } else {
        String info = glucose.getId() + "ele:" + glucose.getElectric();
        ManagementLiveData.getInstance().updateOperationConnect(glucose.getId());
        PocGlucose pocGlucose = GattTool.getPocGlucose(glucose, device, bytes, eDevice);
        if (pocGlucose != null) {
          AlgorithmCallBack callBack = GattTool.algorithm(BApplication.getContext(), pocGlucose, device);
          handleNewGlucose(callBack, device);
        } else {
          MyLog.e("数据为null");
        }
      }
    } else {
      MyLog.w("解析失败");
      DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_END;
      BleGattCallback.getInstance().disConnectGatt();
    }
  }

  private synchronized void test_pull_glucose_series(ProtocolTools.Glucose glucose) {
    MyLog.d("test_pull_glucose_series success " + glucose.toString());
    if (glucose != null) {
      DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_READ;
      dispose();
      PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
      String info = glucose.getId() + "ele:" + glucose.getElectric();
      ManagementLiveData.getInstance().updateOperationConnect(glucose.getId());
      PocGlucose pocGlucose = GattTool.getPocGlucose(glucose, device, glucose.getBytes(), null);
      if (pocGlucose != null) {
        AlgorithmCallBack callBack = GattTool.algorithm(BApplication.getContext(), pocGlucose, device);
        handleNewGlucose(callBack, device, true);
        LineUpTaskGlucoseProcess.getInstance().finishTask(glucose);
      } else {
        MyLog.e("数据为null");
        LineUpTaskGlucoseProcess.getInstance().completedInitiative(false);
      }
    } else {
      MyLog.w("解析失败");
      LineUpTaskGlucoseProcess.getInstance().completedInitiative();
      DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_END;
      BleGattCallback.getInstance().disConnectGatt();
    }
  }

  public void handleNewGlucose(@NonNull AlgorithmCallBack callBack, @NonNull PocDevice device) {
    handleNewGlucose(callBack, device, false);
  }

  /**
   * 新血糖触及处理
   *
   * @param callBack 数据返回
   * @param device   设备数据
   */
  public void handleNewGlucose(@NonNull AlgorithmCallBack callBack, @NonNull PocDevice device, boolean isSeries) {
    if (DATA_SYNCHRONIZATIONS == EnumSynchronous.SYNCHRONOUS_READ) {
      DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_COMPLETE;
    }
    if (callBack.getErrorCode() == AlgorithmCallBack.SUCCESS) {
      if (DATA_SYNCHRONIZATIONS == EnumSynchronous.SYNCHRONOUS_END) {
        //非同步数据状态
        pullDataDelay();
      }
      //正常计算完成 或者上一个对应的ping点失去
      PocGlucose pocGlucose = callBack.getGlucose();
      pocGlucose.setName(device.getName());
      long glucoseId = RepositoryGlucose.getInstance(BApplication.getContext()).insertGlucoseIoThread(pocGlucose);
      if (glucoseId >= 0) {
        device = GattTool.deviceInitComplete(BApplication.getContext(), pocGlucose, device);
        //若是最后一个点就解绑
        if (pocGlucose.getGlucoseId() == EDevice.getEnumDevice(device.getName()).getEndNumber() - 1 || pocGlucose.getErrorCode() == enumError.INFO_COMPLETE_END) {
          if (DATA_SYNCHRONIZATIONS == EnumSynchronous.SYNCHRONOUS_COMPLETE) {
            ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_PULL_END);
          }
          GattTool.unBindInDatabaseIoThread(BApplication.getContext(), device, enumUnBind.UNBIND_COMMAND);
          LineUpTaskGlucoseProcess.getInstance().completedInitiative();
          unBindDevice(device);
        } else if (DATA_SYNCHRONIZATIONS == EnumSynchronous.SYNCHRONOUS_COMPLETE) {
          //同步数据中
          if (!isSeries) {
            requestNextGlucoseData(device);
          }
        }
      } else {
        requestNextGlucoseData(device);
      }
    } else if (callBack.getErrorCode() == AlgorithmCallBack.ERROR_DATA) {
      MyLog.iLog("handleNewGlucose callBack errorCode = " + callBack.getErrorCode());
//            unBindDevice(device);
    } else if (callBack.getErrorCode() == AlgorithmCallBack.ERROR_ALGORITHM) {
      MyLog.iLog("handleNewGlucose callBack errorCode = " + callBack.getErrorCode());
      unBindDevice(device);
    } else if (callBack.getErrorCode() == AlgorithmCallBack.DATA_REPEAT) {
      if (!isSeries) {
        requestNextGlucoseData(device);
      }
    } else if (callBack.getErrorCode() == AlgorithmCallBack.DATA_LOST) {
      if (!isSeries) {
        requestNextGlucoseData(device);
      }
    }
  }

  public void test_unBind_response(EDevice eDevice, BluetoothGatt gatt, byte[] bytes) {
    MyLog.e("test_unBind_response " + HexadecimalTools.ByteArrayToStrs16(bytes));
    if (mProtocolTools.unBind_response(bytes, eDevice)) {
      MyLog.d("test unBind response success");
      PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
      if (device.getAlgorithmVersion() < ConstantsLibrary.ALGORITHM_VERSION) {
        MyLog.w("算法版本错误造成的解除绑定");
        GattTool.unBindInDatabaseIoThread(BApplication.getContext(), device, enumUnBind.UNBIND_COMMAND);
      } else if (unBindType == enumUnBind.UNBIND_RESET) {
        MyLog.w("电池重置造成的解除绑定");
        GattTool.unBindInDatabaseIoThread(BApplication.getContext(), device, enumUnBind.UNBIND_RESET);
      } else {
        GattTool.unBindInDatabaseIoThread(BApplication.getContext(), device, enumUnBind.UNBIND_COMMAND);
      }
    }
    removeHandler();
  }

  /**
   * 设置延时执行断开连接
   *
   * @param delay 延时执行的时间
   */
  private void disConnectTimeout(long delay, BluetoothDevice bluetoothDevice) {
    disconnectDispose();
    disconnectDisposable = Observable.timer(delay, TimeUnit.MILLISECONDS)
      .subscribeOn(Schedulers.io())
      .map(aLong -> {
        PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
        if (device != null && device.isBoundButDisConnect()) {
          ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_DISCONNECT_TIMEOUT);
          BleGattCallback.getInstance().disConnectGatt();
        }
        return device;
      })
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(device -> {
      }, Throwable::printStackTrace);
  }

  /**
   * 延时执行获取同步数据
   */
  private void pullDataDelay() {
    dispose();
    if (ConstantsLibrary.TIME_SECONDS_DISCONNECT > 0) {
      MyLog.d("pullDataDelay " + ConstantsLibrary.TIME_SECONDS_DISCONNECT + " s DisConnect");
      delayDisposable = Observable.timer(ConstantsLibrary.TIME_SECONDS_DISCONNECT, TimeUnit.SECONDS)
        .subscribeOn(Schedulers.io())
        .map(aLong -> {
          BleGattCallback.getInstance().disConnectGatt();
          return true;
        })
        .subscribe(aBoolean -> {

        });
    } else {
      MyLog.d("pullDataDelay " + TIME_DATA_CHECK / 1000 + " s Synchronous data");
      delayDisposable = Observable.timer(TIME_DATA_CHECK, TimeUnit.MILLISECONDS)
        .subscribeOn(Schedulers.io())
        .map(aLong -> {
          requestNextGlucoseData();
          return true;
        })
        .subscribe(aBoolean -> {

        });
    }
  }

  /**
   * 延迟拉取数据
   */
  public void dispose() {
    if (delayDisposable != null && !delayDisposable.isDisposed()) {
      MyLog.i("delayDispose cancel");
      delayDisposable.dispose();
      delayDisposable = null;
    }
  }


  /**
   * 取消连接请求
   */
  public void disconnectDispose() {
    if (disconnectDisposable != null && !disconnectDisposable.isDisposed()) {
      MyLog.i("dispose cancel");
      disconnectDisposable.dispose();
      disconnectDisposable = null;
    }
  }


  /**
   * 向发射器请求下一个血糖数据点
   */
  private void requestNextGlucoseData() {
    if (BApplication.getContext() == null) {
      return;
    }
    mDisposable = Observable.just(BApplication.getContext())
      .subscribeOn(Schedulers.io())
      .map(context -> RepositoryDevice.getInstance(context).getLatestDeviceIoThread())
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(pocDevice -> {
        if (pocDevice != null && pocDevice.isBoundAndConnect()) {
          requestNextGlucoseData(pocDevice);
        }
      }, throwable -> {
        removeHandler();
      });
  }

  /**
   * 向发射器请求下一个血糖数据点
   *
   * @param device 正绑定的发射器
   */
  private void requestNextGlucoseData(PocDevice device) {
    if (BApplication.getContext() == null) {
      return;
    }
    mDisposable = Observable.just(device)
      .subscribeOn(Schedulers.io())
      .map(pocDevice -> RepositoryGlucose.getInstance(BApplication.getContext()).getMaxGlucoseIdIoThread(pocDevice.getId()))
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(integer -> {
        if (DATA_SYNCHRONIZATIONS == EnumSynchronous.SYNCHRONOUS_READ) {
          return;
        }
        DATA_SYNCHRONIZATIONS = EnumSynchronous.SYNCHRONOUS_READY;
        EDevice eDevice = EDevice.getEnumDevice(device.getName());
        byte[] data = mProtocolTools.pullGlucose_series_request(integer + 1, Number, eDevice);
        MyLog.e("请求发送 " + HexadecimalTools.ByteArrayToStrs16(data));
        BleGattCallback.getInstance().writeCharacteristic(data);
      }, throwable -> {
        removeHandler();
      });
  }

  /**
   * 通过命令解除发射器与接收器的绑定
   *
   * @param device 设备信息
   */
  public void unBindDevice(@NonNull PocDevice device) {
    if (!ConstantsLibrary.IS_SIGN_IN && ConstantsLibrary.SYNCHRONOUS_DATA != null) {
      return;
    }
    if (device.isBoundAndConnect()) {
      LineUpTaskGlucoseProcess.getInstance().completedInitiative();
      MyLog.d("unBindDevice command send");
      EDevice eDevice = EDevice.getEnumDevice(device.getName());
      byte[] bytes = mProtocolTools.unBind_request(eDevice);
      if (bytes != null) {
        if (BleGattCallback.getInstance().writeCharacteristic(bytes)) {
          ManagementLiveData.getInstance().updateOperationConnect(EnumConnect.CONNECT_UNBIND_START);
        }
      }
    } else {
      unBindType = enumUnBind.NONE;
      MyLog.w("设备不是绑定且连接的状态");
    }
  }

  private void reset_response(BluetoothGatt gatt, EDevice eDevice, byte[] data) {
    try {
      MyLog.i("reset_response " + HexadecimalTools.ByteArrayToStrs16(data));
      TransmitterReset reset = mProtocolTools.reset_response2(data, eDevice);
      MyLog.i("查看重置命令的信息 " + reset.toString());
      PocDevice device = RepositoryDevice.getInstance(BApplication.getContext()).getLatestDeviceIoThread();
      if (device != null && device.isBound()) {
        if (reset.isBind()) {
          setDeviceInDatabaseConnect(gatt, device);
        } else {
          unBindType = enumUnBind.UNBIND_RESET;
          GattTool.unBindInDatabaseIoThread(BApplication.getContext(), device, enumUnBind.UNBIND_RESET);
        }
      }
    } catch (Exception e) {
      MyLog.e(" " + e.getMessage());
      BleGattCallback.getInstance().disConnectGatt();
    }
  }

}
