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.ArrayList;
import java.util.UUID;

/**
 * Created by lvwang2002 on 16/3/2.
 */
public class BleNativeHMDGlucoseDevice extends BleNativeDevice {
    private String TAG ="BLE_ENUO_GLUCOSE_DEVICE";

    public static final String UUID_BTLE_SERVICE = "00001808-0000-1000-8000-00805f9b34fb";
    public static final String UUID_BTLE_SEND = "49535343-8841-43f4-a8d4-ecbe34729bb3";
    public static final String UUID_BTLE_RECEIVE = "00002a18-0000-1000-8000-00805f9b34fb";
    public static String SERVICES_DEVICE = "0000180a-0000-1000-8000-00805f9b34fb";

    private String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
    private static String UUID_DEVICE_INFO = "00002a25-0000-1000-8000-00805f9b34fb";


    BleDevice mDevice = null;
    BleDeviceManager mDeviceManager = null;

    public BleNativeHMDGlucoseDevice(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);
    }



    BleNativeHMDGlucoseDeviceCallback mDeviceCallback = null;
    public interface BleNativeHMDGlucoseDeviceCallback extends BleNativeDevice.BleNativeDeviceCallback{
        public void onResult(BleDevice device, double data);
        public void onSerialNumber(BleDevice device, String serialNumber);
    }

    @Override
    public void  setNativeDeviceCallback(BleNativeDevice.BleNativeDeviceCallback deviceCallback){
        mDeviceCallback = (BleNativeHMDGlucoseDeviceCallback) 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;
            }


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

    }

    @Override
    public void setIsGetWriteDescription(BluetoothGatt gatt,boolean flag){
        Log.i(TAG,"开始读取设备编号");

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

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



        BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID.fromString(UUID_DEVICE_INFO));
        if(characteristic == null){
            mDeviceManager.uhOh(mDevice,"not get device Characteristic");
            return;
        }

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

        gatt.readCharacteristic(characteristic);
    }



    /** 接收并处理数据  */
    @Override
    public void receiveData(BluetoothGattCharacteristic characteristic){
        ArrayList<String> datas = broadcastUpdate(characteristic);

        if(characteristic.getUuid().equals(UUID.fromString(UUID_DEVICE_INFO))){
            final String serialNumber = parseSerialNumber(datas);
            Log.i(TAG,"parse serial number"+serialNumber);

            if(postMainThreadNeeded()){
                post(new Runnable() {
                    @Override
                    public void run() {
                        mDeviceCallback.onSerialNumber(mDevice,serialNumber);
                    }
                });
            }else{
                mDeviceCallback.onSerialNumber(mDevice,serialNumber);
            }

        }else{
            final double data = parseData(datas);


            if(postMainThreadNeeded()){
                post(new Runnable() {
                    @Override
                    public void run() {
                        mDeviceCallback.onResult(mDevice,data);
                    }
                });
            }else{
                mDeviceCallback.onResult(mDevice,data);
            }
        }

    }

    private ArrayList<String> broadcastUpdate(
                                 final BluetoothGattCharacteristic characteristic) {

        // For all other profiles, writes the data formatted in HEX.
        final byte[] data = characteristic.getValue();
        Log.e(TAG, "" + data);
        ArrayList<String> stringArray = new ArrayList<String>();

        if (data != null && data.length > 0) {
            for (int i = 0; i < data.length; i++) {
                // TODO 处理数据
                String hex = Integer.toHexString(data[i] & 0xFF);
                if (hex.length() == 1) {
                    hex = '0' + hex;
                }
                // String str = String.format("%02X", data[i]);
                stringArray.add(hex);
            }
        }

        return stringArray;
    }
    private String parseSerialNumber(ArrayList<String> stringArray){
        String deviceNum = "";
        for (int i = 0; i < stringArray.size(); i++) {

            deviceNum += stringArray.get(i);
        }

        return deviceNum;
    }

    private double parseData(ArrayList<String> stringArray){
        double v = 0;
        String dataHex = stringArray.get(12) + stringArray.get(13);
        String dataResult = Integer.toBinaryString(Integer
                .parseInt(dataHex, 16));
        String dataM = dataHex.substring(1);
        String dataN = dataResult.substring(0, 4);
        int resultM = Integer.parseInt(dataM, 16);
        int resultN = Integer.parseInt(dataN, 2);

        v = resultM / Math.pow(10, (16 - resultN));// mmol/l
        return  v;
    }


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