package com.device.comm.mylibrary.NativeDevice;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.text.format.Time;
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.RNLog;
import com.device.comm.mylibrary.UpdateLoop;

import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.UUID;

/**
 * Created by lvwang2002 on 16/1/25.
 */
public class BleNativeBioLandGlucoseDevice extends BleNativeDevice {
    private String TAG ="RN_BIOLAND_DEVICE";

    public static final String UUID_BTLE_SERVICE = "00001000-0000-1000-8000-00805f9b34fb";
    public static final String UUID_BTLE_SEND = "00001001-0000-1000-8000-00805f9b34fb";
    public static final String UUID_BTLE_RECEIVE = "00001002-0000-1000-8000-00805f9b34fb";
    private String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";


    private Time time = null;

    /**
     * 包头
     */
    public final static byte CMD_HEAD = 0x5A;
    /**
     * 包类别
     */
    public final static byte CMD_CATEGORY_ZERO = 0x00;
    public final static byte CMD_CATEGORY_ONE = 0x01;
    public final static byte CMD_CATEGORY_TWO = 0x02;
    public final static byte CMD_CATEGORY_THReE = 0x03;
    public final static byte CMD_CATEGORY_FOUR = 0x04;
    public final static byte CMD_CATEGORY_FIVE = 0x05;
    public final static byte CMD_CATEGORY_SIX = 0x06;
    /**
     * 包长
     */
    public final static byte CMD_LENGTH_TEN = 0x0A;
    public final static byte CMD_LENGTH_ELEVEN = 0x0B;
    public final static byte CMD_LENGTH_TWELVE = 0x0C;
    public final static byte CMD_LENGTH_THIRTEEN = 0x0D;
    public final static byte CMD_LENGTHY_FOURTEEN = 0x0E;
    public final static byte CMD_LENGTH_FIFTEEN = 0x0F;
    public final static byte CMD_SIXTEEN_THIRTEEN = 0x10;

    private boolean mIsRcvResult = false;

    BleDevice mDevice = null;
    BleDeviceManager mDeviceManager = null;

    public BleNativeBioLandGlucoseDevice(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);
    }
    public synchronized void postDelay(Runnable runnable,long delayMillis){
        final UpdateLoop updateLoop = mDeviceManager.getUpdateLoop();
        updateLoop.postDelay(runnable,delayMillis);
    }


    BleNativeGlucoseDeviceCallback mDeviceCallback = null;
    public interface BleNativeGlucoseDeviceCallback extends BleNativeDeviceCallback{
        public void onResult(BleDevice device, GlucoseData data,String displayName);

    }

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

            postDelay(new Runnable() {
                @Override
                public void run() {
                    //发送数据
//                    sendDataByte(CMD_LENGTH_TEN, CMD_CATEGORY_THReE);
//                    getResult();
                      sendHandShake();
                }
            },1000);


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

    }

    private void sendDataByte(final byte leng, final byte commandType) {

        byte[] sendDataByte = getSystemdate(CMD_HEAD, leng,
                commandType);
        Log.e(TAG, "535 开始发送" );
        sendData(sendDataByte);
    }

    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(mDevice.getDeviceConnect().getGatt() == null){
                return;
            }


            if (mGattCharacteristicTrans.setValue(data)
                    && mDevice.getDeviceConnect().getGatt().writeCharacteristic(mGattCharacteristicTrans)) {
                RNLog.d(TAG, "send data OK");
            }else{
                RNLog.d(TAG,"数据长度不在指定范围内");
            }
        }
    }

    /** 接收并处理数据  */
    @Override
    public void receiveData(BluetoothGattCharacteristic characteristic){

        final byte[] data = characteristic.getValue();
        RNLog.d(TAG,"rev:"+ Bytes2HexString(data, 0,data.length));
//        55 12 00 25 01 16 02 02 31 37 42 30 30 30 33 32 37 7F

        int command = data[2]&0xff;

        switch (command){
            case 0:{
//                getResult();
            }
            break;

            case 3:{
                String result4 = getShort(data, 9) + "";
                final String value = swithXueTang(result4);
                RNLog.d(TAG,"result"+value);
//                mIsRcvResult = true;
                post(new Runnable() {
                    @Override
                    public void run() {
                        mDeviceCallback.onResult(mDevice,data2Glucose(data),value);
                    }
                });
            }
            break;

        }


//        if(data.length<9){
//            return;
//        }
//



//        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[3] & 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));
        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);
    }


    private void sendHandShake(){
//        byte[] data = {(byte)0x5a,(byte)0x04,(byte)0x09,(byte)0x69};
//        5A 0A 00 11 0C 0D 0F 0E 26 D3
        byte[] data = {(byte)0x5a,(byte)0x0a,(byte)0x00,(byte)0x11,(byte)0x0c,
                        (byte)0x0d,(byte)0x0f,(byte)0x0e,(byte)0x26,(byte)0xd3};
        sendData(data);
    }


    byte[] cmdData = new byte[] {};

    public byte[] getSystemdate(byte cmdStart, byte cmdLength, byte cmdSort) {
        byte cmdCheck = 0;

        time = new Time();
        time.setToNow();
        cmdData = new byte[cmdLength];
        cmdData[0] = (byte) cmdStart;
        cmdData[1] = (byte) cmdLength;
        cmdData[2] = (byte) cmdSort;
        cmdData[3] = (byte) (time.year - 2000);
        cmdData[4] = (byte) ((byte) time.month + 1);
        cmdData[5] = (byte) time.monthDay;
        cmdData[6] = (byte) time.hour;
        cmdData[7] = (byte) time.minute;
        cmdData[8] = (byte) time.second;

        for (int i = 0; i < cmdData.length; i++) {
            cmdCheck += cmdData[i];
        }
        cmdData[9] = (byte) (cmdCheck + 2);
        // cmdData[9] = 0;
        // cmdData[10] = 0;cmdData= new byte[] {90, 11, 5, 15, 6, 1, 8, 56,
        // (byte) 192,0,0};
        return cmdData;
    }
    public static short getShort(byte[] b, int index) {
        return (short) (((b[index + 1] << 8) | b[index + 0] & 0xff));
    }

    public String swithXueTang(String result) {
        double resultValue = Double.parseDouble(result);
        resultValue = resultValue / 18;
        NumberFormat nf = NumberFormat.getInstance();
        nf.setRoundingMode(RoundingMode.HALF_UP);// 设置四舍五入
        nf.setMinimumFractionDigits(1);// 设置最小保留几位小数
        nf.setMaximumFractionDigits(1);// 设置最大保留几位小数
        return nf.format(resultValue);

    }

    Thread mThread = null;

    private void getResult(){
//         if(mThread !=null){
////             mThread.stop();
//         }

         mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    if(mDevice.getDeviceConnect().getGatt() == null){
                        return;
                    }


                    RNLog.d(TAG,"request result");
                    sendDataByte(CMD_LENGTH_TEN, CMD_CATEGORY_THReE);
                    try{
                        Thread.sleep(500);
                    }catch (InterruptedException error){
                        error.printStackTrace();
                    }
                }
            }
        });
        mThread.start();
    }

}
