package com.device.comm.mylibrary.NativeDevice;

import android.bluetooth.BluetoothDevice;
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.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Timer;
import java.util.UUID;

/**
 * Created by lvwang2002 on 16/2/19.
 */
public class BleNativeCholesterolDevice extends BleNativeDevice {

    private String TAG ="BLE_CHOLESTEROL_DEVICE";

    public static final String UUID_BTLE_SERVICE = "C14D2C0A-401F-B7A9-841F-E2E93B80F631";
//    public static final String UUID_BTLE_SEND = "81eb77bd-89b8-4494-8a09-7f83d986ddc7";
    public static final String UUID_BTLE_RECEIVE = "81eb77bd-89b8-4494-8a09-7f83d986ddc7";
    private String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";

    BleDevice mDevice = null;
    BleDeviceManager mDeviceManager = null;

    public BleNativeCholesterolDevice(BleDevice device, BleDeviceManager deviceManager){
        mDevice = device;
        mDeviceManager = deviceManager;

    }


    @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);
    }



    BleNativeCholesterolDeviceCallback mDeviceCallback = null;
    public interface BleNativeCholesterolDeviceCallback extends BleNativeDevice.BleNativeDeviceCallback{
        public void onResult(BleDevice device, String[] result);
    }

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


    BluetoothGattCharacteristic mNotifyCharacteristic = null;
    BluetoothGattService mDeviceService = null;
    BluetoothGattCharacteristic mGattCharacteristicTrans = null;

    boolean mIsGetWriteDescription  = false;

    @Override
    public void setIsGetWriteDescription(BluetoothGatt gatt,boolean flag){
        Log.i(TAG,"set WriteDescription"+flag);

        mIsGetWriteDescription = flag;
    }

    private Timer mCheckTimer;

    @Override
    public void onServicesDiscovered_mainThread(final BluetoothGatt gatt, final int gattStatus) {
        Log.i(TAG,"找到服务,开始处理"+gattStatus);
        if( gattStatus == BluetoothGatt.GATT_SUCCESS ) {

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

            for(BluetoothGattCharacteristic characteristic:mDeviceService.getCharacteristics()){
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if(characteristic.getUuid().equals(UUID.fromString(UUID_BTLE_RECEIVE)) &&
                  ((characteristic.getProperties() & 0x2) != 0)){
                    Log.i(TAG,"找到读属性");
                    mNotifyCharacteristic = characteristic;

                }

                if(characteristic.getUuid().equals(UUID.fromString(UUID_BTLE_RECEIVE)) &&
                        ((characteristic.getProperties() & 0x4) != 0)){
                    Log.i(TAG,"找到写属性");
                    mGattCharacteristicTrans = characteristic;

                }
            }

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(mDevice.getBluetoothDevice().getBondState() != BluetoothDevice.BOND_BONDED){
                //如果没有绑定,读加密属性
                Log.i(TAG,"还没绑定,绑定后再进行");
                gatt.readCharacteristic(mNotifyCharacteristic);
                return;
            }


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

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


            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;
        }


//        Log.i(TAG, "set notify");
//        boolean bool = gatt.setCharacteristicNotification(characteristic, enable);
//        if (!bool) {
//            Log.i(TAG, "Seting proper notification status for characteristic failed!");
//        }
//        BluetoothGattDescriptor localBluetoothGattDescriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
//        if (localBluetoothGattDescriptor != null)
//        {
//            byte[] arrayOfByte = enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;
//            localBluetoothGattDescriptor.setValue(arrayOfByte);
//            gatt.writeDescriptor(localBluetoothGattDescriptor);
//        }

        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();
        getXuezhiData(data);

//        Log.d(TAG,data.toString());

//        if(!checkedCommandIntegrity(data)){
//            Log.d(TAG,"完整性检测失败");
//            return;
//        }
//
//        Log.d(TAG,"完整性检测成功");
//
//        if(postMainThreadNeeded()){
//            post(new Runnable() {
//                @Override
//                public void run() {
//                    mDeviceCallback.onResult(mDevice,data2Glucose(data));
//                }
//            });
//        }else{
//            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]});
//        }
    }

//    private StringBuilder mXuezhiValue = new StringBuilder();// ASCII
    private String mXuezhiValue = "";
    private boolean dataR;


    private void getXuezhiData(byte[] data) {
        // // 处理血脂数据
        // mXuezhiData.setVisibility(View.VISIBLE);
        // mOtherLayout.setVisibility(View.GONE);
        Log.e(TAG,"血脂数据:"+Bytes2HexString(data,0,data.length));
        String xuezhiData;
        try {
            xuezhiData = new String(data, "UTF-8");
//            mXuezhiValue.append(xuezhiData);
            mXuezhiValue += xuezhiData;

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        Log.d(TAG,mXuezhiValue);


        int size = data.length;
        String[] dataArr = null;

        if (size >= 4) {
            // 连续两个空行0x0d，0x0a
            if ((data[size - 2] == 13 && data[size - 1] == 10 && data[size - 4] == 13 && data[size - 3] == 10 ) ||
                (data[size - 2] == 10 && data[size - 1] == 13 && data[size - 4] == 10 && data[size - 3] == 13) ) {
//                    String text = mXuezhiValue.toString();
                dataArr = getValue(mXuezhiValue);

                final String[] myDataArray = dataArr;
                Log.d(TAG,"chol"+dataArr[0]);
                Log.d(TAG,"hdl"+dataArr[1]);
                Log.d(TAG,"trig"+dataArr[2]);
                Log.d(TAG,"ldl"+dataArr[3]);
                mXuezhiValue = "";
                if(postMainThreadNeeded()) {
                    post(new Runnable() {
                        @Override
                        public void run() {
                            mDeviceCallback.onResult(mDevice,myDataArray);
                        }
                    });
                }else{
                    mDeviceCallback.onResult(mDevice,myDataArray);
                }

            }
        }


        // text = text.replace("CHOL:", "总胆固醇(CHOL):");
        // text = text.replace("LDL:", "低密度脂蛋白胆固醇(LDL):");
        // text = text.replace("TRIG:", "甘油三脂(TRIG):");
        // text = text.replace("CHOL/HDL:",
        // "总胆固醇/高密度脂蛋白胆固醇(CHOL/HDL):");
        // text = text.replace("HDL:", "高密度脂蛋白胆固醇(HDL):");
    }

    String[] dataString = null;
    String[] dataString2 = null;

    private String[] getValue(String text) {

        dataString = text.split("\n");
        dataString2 = new String[7];
        Log.e("text", text);
        Log.e("dataString", String.valueOf(dataString.length));

        if (dataString.length >= 7) {
            String chol = dataString[2];
            String hdl = dataString[3];
            String trig = dataString[4];
            String ldl = dataString[6];
            chol = chol.split("mg")[0];
            chol = chol.split(":")[1];
            hdl = hdl.split("mg")[0];
            hdl = hdl.split(":")[1];
            trig = trig.split("mg")[0];
            trig = trig.split(":")[1];
            ldl = ldl.split("mg")[0];
            ldl = ldl.split(":")[1];

            dataString2[0] = chol;
            dataString2[1] = hdl;
            dataString2[2] = trig;
            dataString2[3] = ldl;
            dataR = true;
        } else {
            if (dataString != null && dataString2 != null) {
                dataString = null;
                dataString2 = null;
            }
//            UIHelper.showToast(CheckOperationActivity.this,
//                    R.string.data_error, Gravity.BOTTOM);
        }
        return dataString2;

    }

    // 计算CRC
    private int uiCRC16(int uiStart, ArrayList<Byte> dataList) {
        int ucSaveLO;
        int wCrc16Lo;
        int wCrc16 = uiStart;
        for (int k = 0; k < dataList.size(); k++) {

            if (dataList.get(k) != 6) {
                wCrc16Lo = wCrc16 & 0x00FF;
                wCrc16Lo ^= dataList.get(k);
                wCrc16Lo &= 0x00FF;
                wCrc16 = wCrc16 & 0xFF00;
                wCrc16 += wCrc16Lo;
                for (int i = 0; i < 8; i++) {
                    ucSaveLO = wCrc16 & 0x01;
                    wCrc16 /= 2;
                    if (ucSaveLO == 1) {
                        wCrc16 ^= 0xA001;
                    }
                }

            } else {
                break;
            }
        }
        return wCrc16;
    }

    @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);
    }
}
