

package com.device.comm.mylibrary.NativeDevice;
        import android.bluetooth.BluetoothGatt;
        import android.bluetooth.BluetoothGattCharacteristic;
        import android.bluetooth.BluetoothGattDescriptor;
        import android.bluetooth.BluetoothGattService;
        import android.util.Log;
        import com.device.comm.mylibrary.BleDevice;
        import com.device.comm.mylibrary.BleDeviceConnect;
        import com.device.comm.mylibrary.BleDeviceManager;
        import com.device.comm.mylibrary.UpdateLoop;
        import java.util.UUID;


public class BleNativeEnuoTDGlucoseDevice extends BleNativeDevice {
    private String TAG ="BleNativeEnuoTDGlucoseDevice";

    public static final String UUID_BTLE_SERVICE = "49535343-fe7d-4ae5-8fa9-9fafd205e455";
    public static final String UUID_BTLE_SEND = "49535343-8841-43f4-a8d4-ecbe34729bb3";
    public static final String UUID_BTLE_RECEIVE = "49535343-1e4d-4bd9-ba61-23c647249616";
    private String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";


    BleDevice mDevice = null;
    BleDeviceManager mDeviceManager = null;

    public BleNativeEnuoTDGlucoseDevice(BleDevice device, BleDeviceManager deviceManager){
        mDevice = device;
        mDeviceManager = deviceManager;
        Log.d(TAG, "扫描到BleNativeEnuoTDGlucoseDevice: ");

    }


    @Override
    public String getNotifyCharacteristicUUID() {
        return UUID_BTLE_RECEIVE;
    }

    @Override
    public String getDeviceServiceUUID(){
        return  UUID_BTLE_SERVICE;
    }

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

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

        updateLoop.postIfNeeded(runnable);
    }

    private boolean postMainThreadNeeded() {
        return mDeviceManager.getMainUpdateLoop().postNeeded();
    }

    private void postMainThread(final Runnable runnable) {
        final UpdateLoop updateLoop = mDeviceManager.getMainUpdateLoop();

        updateLoop.postIfNeeded(runnable);
    }



    BleNativeEnuoTDGlucoseDeviceCallback mDeviceCallback = null;
    public interface BleNativeEnuoTDGlucoseDeviceCallback extends BleNativeDevice.BleNativeDeviceCallback{
        public void onResult(BleDevice device, GlucoseData data);

    }

    @Override
    public void  setNativeDeviceCallback(BleNativeDevice.BleNativeDeviceCallback deviceCallback){
        mDeviceCallback = (BleNativeEnuoTDGlucoseDeviceCallback) deviceCallback;
    }


    BluetoothGattCharacteristic mNotifyCharacteristic = null;
    BluetoothGattService mDeviceService = null;
    BluetoothGattCharacteristic mGattCharacteristicTrans = null;
    @Override
    public void onServicesDiscovered_mainThread(final BluetoothGatt gatt, final int gattStatus) {
        Log.d(TAG,"找到服务,开始处理");

        if( gattStatus == BluetoothGatt.GATT_SUCCESS ) {
            mDeviceService = gatt.getService(UUID.fromString(UUID_BTLE_SERVICE));
            if(mDeviceService == null){
                mDeviceManager.uhOh(mDevice,"not get device server");
                return;
            }

            mNotifyCharacteristic = mDeviceService.getCharacteristic(UUID.fromString(UUID_BTLE_RECEIVE));
            if(mNotifyCharacteristic == null){
                mDeviceManager.uhOh(mDevice,"not get device Characteristic");
                return;
            }

            mGattCharacteristicTrans = mDeviceService.getCharacteristic(UUID.fromString(UUID_BTLE_SEND));
            if(mNotifyCharacteristic == null){
                mDeviceManager.uhOh(mDevice,"not get send device Characteristic");
                return;
            }
            mGattCharacteristicTrans.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);



            if( postNeeded() ) {
                post(new Runnable() {
                    @Override
                    public void run() {
                        enableNotification(gatt,true,mNotifyCharacteristic);
                    }
                });
            } else {
                enableNotification(gatt,true,mNotifyCharacteristic);
            }


        } else {
            mDeviceManager.uhOh(mDevice,"service status error:"+gattStatus);
        }

    }

    private void enableNotification(final BluetoothGatt gatt,final boolean enable,final BluetoothGattCharacteristic characteristic) {
        if (gatt == null){
            Log.e(TAG,"gatt 为空");
            return;
        }

        if (!(gatt.setCharacteristicNotification(characteristic, enable))){
            Log.e(TAG,"设置Gatt失败");
            mDeviceManager.uhOh(mDevice,"set gatt notify error");
            return;
        }

        BluetoothGattDescriptor clientConfig = characteristic.getDescriptor(UUID
                .fromString(CLIENT_CHARACTERISTIC_CONFIG));
        if (clientConfig == null){
            Log.e(TAG,"clientConfig为空,但好像也不是特别影响");
            return;
        }
        byte[] b = {
                (byte) 0x00, (byte) 0x01
        };
        try{
            clientConfig.setValue(b);
        }catch (Exception e) {
            mDeviceManager.uhOh(mDevice,"null exception");
            return;
        }

        if (enable) {
            Log.i(TAG, "enable notification");
            clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        } else {
            Log.i(TAG, "disable notification");
            clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        }

        if(!gatt.writeDescriptor(clientConfig)){
            Log.e(TAG,"write descriptor error");

            mDeviceManager.uhOh(mDevice,"write descriptor error");
            return;
        };

    }

    private void sendData(byte[] data) {

        if (data != null && data.length > 0 && data.length < 21) {
            if (mGattCharacteristicTrans.setValue(data)
                    && mDevice.getDeviceConnect().getGatt().writeCharacteristic(mGattCharacteristicTrans)) {
                Log.d(TAG, "send data OK");
            }else{
                Log.d(TAG,"数据长度不在指定范围内");
            }
        }
    }

    /** 接收并处理数据  */
    @Override
    public void receiveData(BluetoothGattCharacteristic characteristic){
        final byte[] data = characteristic.getValue();
        if(!checkedCommandIntegrity(data)){
            Log.d(TAG,"完整性检测失败");
            return;
        }

        Log.d(TAG,"完整性检测成功");

        if(postMainThreadNeeded()){
            post(new Runnable() {
                @Override
                public void run() {
                    if(mDeviceCallback == null){
                        return;
                    }

                    mDeviceCallback.onResult(mDevice,data2Glucose(data));
                }
            });
        }else{
            if(mDeviceCallback == null){
                return;
            }

            mDeviceCallback.onResult(mDevice,data2Glucose(data));
        }

        if( postNeeded() ) {
            post(new Runnable() {
                @Override
                public void run() {
                    sendData(new byte[]{(byte)0xFF,data[2]});
                }
            });
        } else {
            sendData(new byte[]{(byte)0xFF,data[2]});
        }
    }

    public static  boolean checkedCommandIntegrity(byte[] b){
        //长度检测
        if(b.length<7){
            return false;
        }

        //报文头检测
        if(b[0] != 0x40){
            return  false;
        }

        //有效命令长度检测
        if(b[3] != (b.length - 6)){
            return false;
        }


        if(!checkedCommandCRC(b)){
            //和校验
            return false;
        }

        if(checkedRepeatCommand(b)){
            return false;
        }

        return true;
    }

    public static boolean checkedCommandCRC(byte[] b){
        byte[] a = new byte[10];
        System.arraycopy(b, 4, a, 0, 10);
        int crcValue = BleDeviceCRC.calcCrc16(a,0,10,65535);
        long high = ((long) (b[15] & 0xFF))*256;
        long result = high + (long)(b[14] & 0xFF);
        return result == crcValue;
    }

    private static int queId = -1;
    /** 校验是否是重复指令 */
    public static boolean checkedRepeatCommand(byte[] b){
        int m = (b[2]&0xff);
        if(m == queId){
            return true;
        }
        //2.将该条命令的顺序id写入缓存
        queId = m;

        //4.返回false.
        return false;
    }

    public GlucoseData data2Glucose(byte[] data){
        GlucoseData glucoseData = new GlucoseData();
        glucoseData.setYear(2000+(data[6] & 0xff));
        glucoseData.setMonth(data[4] & 0xff);
        glucoseData.setDay(data[5] & 0xff);
        glucoseData.setHour(data[7] & 0xff);
        glucoseData.setMinute(data[8] & 0xff);
        glucoseData.setGlucose((data[9]&0xff) + 256*(data[10]&0xff));
        glucoseData.setMask(data[11]&0xff);
        glucoseData.setFlagValue((data[12]&0xff) + 256*(data[13]&0xff));
        return glucoseData;
    }

    @Override
    public String getDeviceDisplayName(){
        return "益优血糖血酮测试仪";
    }

    @Override
    public boolean disableNotifications() {
        BleDeviceConnect connect  = mDevice.getDeviceConnect();
        if(connect == null){
            return false;
        }

        BluetoothGatt gatt = connect.getGatt();
        if (gatt == null || mNotifyCharacteristic == null)
            return false;

        if (!(gatt.setCharacteristicNotification(mNotifyCharacteristic, false)))
            return false;

        BluetoothGattDescriptor clientConfig = mNotifyCharacteristic.getDescriptor(UUID.fromString(this.CLIENT_CHARACTERISTIC_CONFIG));
        if (clientConfig == null)
            return false;

        Log.i(TAG, "disable notification");
        clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);

        return gatt.writeDescriptor(clientConfig);
    }
}
