package com.device.comm.mylibrary;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;

import com.device.comm.mylibrary.NativeDevice.BleNativeDevice;
import com.device.comm.mylibrary.NativeDevice.BleNativeEnuoBPDevice;
import com.device.comm.mylibrary.NativeDevice.InvsIdCard;
import com.device.comm.mylibrary.NativeDevice.InvsUid;
import org.apache.commons.lang3.ArrayUtils;
import org.xml.sax.helpers.LocatorImpl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by lvwang2002 on 2016/12/12.
 */
public class BTBioHermesDevice  extends BleDevice {
    private String TAG = "BT_CLASSIC_DEVICE";
    private static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";// 蓝牙服务器的标识

    protected String mAddr1 = null;
    protected String mAddr = "";
    protected Timer mTimer = null;
    protected TimerTask mTimerTask = null;
    public Context mContext = null;
    protected static final int Suc_RecvContinue = 0;
    protected static final int Suc_RecvOk = 1;
    protected static final int Err_CheckHead = 2;
    protected static final int Err_CheckCrc = 3;
    protected int mResult = 0;
    protected int mPos = 0;
    protected int mDataLen = 0;
    protected byte[] mData = new byte['ஸ'];
    public InvsIdCard mInvsIdCard = null;
    //    protected IClientCallBack mCallback = null;
    private ReentrantReadWriteLock mRxLock = new ReentrantReadWriteLock();
    protected int m_iRecvLen = 0;
    protected int mValue = 0;
    protected byte[] mParam = null;
    protected int mPosExt = 0;
    protected int mPackNum = 0;
    protected byte[] mDataExt = new byte['ஸ'];
    protected byte[] mWlt = null;
    protected int mCmd = 0;
    private BluetoothAdapter mBltAdapter;

    private int mConnect = 0;

    private BluetoothSocket mSocket = null;
    private OutputStream os = null;
    private InputStream is = null;

    private String mMacAddress;
    private BleDeviceManager mDeviceManager;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothDevice mBluetoothDevice;
    public BTBioHermesDevice(BluetoothAdapter bluetoothAdapter,
                              BleDeviceManager deviceManager,
                              BluetoothDevice bluetoothDevice){
        mDeviceManager = deviceManager;
        mMacAddress = bluetoothDevice.getAddress();
        mBluetoothAdapter = bluetoothAdapter;
        mBluetoothDevice = bluetoothDevice;

    }


    public BluetoothDevice getBluetoothDevice(){
        mDeviceManager.stopScan();

        return mBluetoothDevice;
    }

    public void tryConnect(){
        mDeviceManager.stopScan();

        connect(mBluetoothDevice);

    }

    @Override
    public String getMacAddress(){
        return mMacAddress;
    }

    public interface BTBioHermesDeviceCallback extends BleDeviceCallback{
        public void onConnect(BleDevice device);
        public void onDisconnect(BleDevice device);
        public void onResult(BleDevice device, float value);
        public void onError(BleDevice device, String error);
    }

    BTBioHermesDeviceCallback mClassicDeviceCallback = null;
    public  void setDeviceCallback(BTBioHermesDeviceCallback deviceCallback) {
        mClassicDeviceCallback = deviceCallback;
    }

    private DeviceConnectState mDeviceState = DeviceConnectState.Discovered; //0:被发现未被连接 1:正在连接 2:已经连接上 3.断开连接

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


    private BluetoothSocket mBluetoothSocket = null;

    @Override
    /** 蓝牙连接 */
    public void connect(BleDeviceCallback deviceCallback){
        mClassicDeviceCallback = (BTBioHermesDeviceCallback) deviceCallback;
        final BluetoothDevice device  = getBluetoothDevice();
        connect(device);
    }

    public void connect(final BluetoothDevice device) {

        boolean isConnected = btConnect(device);

        if (isConnected) {
            // 记录最新的连接设备名称
            mDeviceState = DeviceConnectState.Connected;
            if(mClassicDeviceCallback ==null) return;
            mClassicDeviceCallback.onConnect(this);

        }else{
            mDeviceState = DeviceConnectState.ConnectFailed;
            mDeviceManager.uhOh(this,"connect error");
        }


    }

    private boolean btConnect(final BluetoothDevice device){
        this.mWlt = null;
        String addr  = device.getAddress();
        if ((addr == null) || (addr == "") || (!BluetoothAdapter.checkBluetoothAddress(addr))) {
//            callOnBtState(false);
            return false;
        }

        if (addr.indexOf("00:0E:0B") == 0) {
            this.mAddr1 = addr;
            addr = "00:0E:0E" + this.mAddr1.substring(8);
        } else {
            this.mAddr1 = null;
        }

        this.mAddr = addr;
        if (!initialize()) {
//            callOnBtState(false);
            return false;
        }

        if (!initSock(addr)) {
//            callOnBtState(false);
            return false;
        }

        if (!connSock()) {
//            callOnBtState(false);
            return false;
        }

        this.mRecvThread = new RecvThread();
        this.mRecvThread.start();

        return true;
    }




//    ACTION_BOND_STATE_CHANGED



    public void disconnect(){
        this.mWlt = null;
        this.mRxLock.writeLock().lock();
        if (this.mSocket != null) {
            try {
                if (this.os != null)
                    this.os.close();
                if (this.is != null)
                    this.is.close();
                this.mSocket.close();
            }
            catch (Exception localException) {}
            this.os = null;
            this.is = null;
            this.mSocket = null;
        }
        this.mRxLock.writeLock().unlock();


        mBluetoothSocket = null;
        mDeviceState = DeviceConnectState.Disconnect;
        mDeviceManager.removeDevice(this);

        if(mClassicDeviceCallback ==null) return;
        mClassicDeviceCallback.onDisconnect(this);
    }

    public boolean initialize() {
        this.mBltAdapter = BluetoothAdapter.getDefaultAdapter();
        if (this.mBltAdapter == null) {
            return false;
        }

        if (!this.mBltAdapter.isEnabled()) {
            this.mBltAdapter.enable();
        }

        return true;
    }

    private boolean initSock(String addr) { this.mBltAdapter.cancelDiscovery();
        BluetoothDevice device = this.mBltAdapter.getRemoteDevice(addr);
        try
        {
            this.mSocket = device.createInsecureRfcommSocketToServiceRecord(InvsUid.MY_UUID);
        } catch (IOException e) {
            return initSock1(device);
        }

        return true;
    }


    private boolean initSock1(BluetoothDevice device)
    {
        Method m = null;
        try {
            m = device.getClass().getMethod("createRfcommSocket", new Class[] { Integer.TYPE });
            try {
                this.mSocket = ((BluetoothSocket)m.invoke(device, new Object[] { Integer.valueOf(1) }));
                return true;
            }
            catch (IllegalArgumentException localIllegalArgumentException) {}catch (IllegalAccessException localIllegalAccessException) {}catch (InvocationTargetException localInvocationTargetException) {}




            return false;
        } catch (NoSuchMethodException localNoSuchMethodException) {}
        return false;
    }

    private boolean connSock()
    {
        new Thread()
        {
            public void run()
            {
                try
                {
                    mSocket.connect();
                    mConnect = 1;
                } catch (IOException e) {
                    mConnect = -1;
                }

            }
        }.start();
        this.mConnect = 0;
        int iCount = 0;
        do {
            SystemClock.sleep(150L);
            if (this.mConnect != 0) {
                break;
            }
            iCount++; } while (iCount <= 100);
//        return false;



        if (this.mConnect == -1) {
            return false;
        }
        try
        {
            this.os = this.mSocket.getOutputStream();
            this.is = this.mSocket.getInputStream();
        } catch (IOException e) {
            return false;
        }
        return true;
    }


    public static final String msg = "invs.blt.readcard";

    public class BaseThread extends Thread { public BaseThread() {}
        public boolean mOver = false;

        public boolean isOver() { return (interrupted()) || (this.mOver); }

        public void over()
        {
            interrupted();
            this.mOver = true;
        }
    }

    RecvThread mRecvThread = null;
    public class RecvThread extends BaseThread {
        public RecvThread() { super(); }

        int m_iBufLen = 4096;
        int mCount = 0;
        byte[] mDeviceData = {};

        public void run() {
//            Blt2.this.callOnBtState(true);
            while (!isOver()) {
                recvData();
            }

//            Blt2.this.callOnBtState(false);
        }

        public void recvData() {
            Log.i(TAG,"读取数据!!!!!");
            try {
                byte[] data = new byte[100];
                int iRecvLen = is.read(data);
                data = Arrays.copyOfRange(data,0,iRecvLen);
                Log.i(TAG,"received data:"+Bytes2HexString(data,0,data.length));
                if(!isTransferFin(data)){
                    mDeviceData = ArrayUtils.addAll(mDeviceData,data);
                    return;
                }

                Log.i(TAG,"接收完成,读取数据:"+iRecvLen+Bytes2HexString(mDeviceData,0,mDeviceData.length));
                byte[] deviceData = ArrayUtils.clone(mDeviceData);
                mDeviceData = new byte[0];

                mRxLock.writeLock().lock();

                if(deviceData.length>40){
                    byte[] myData = Arrays.copyOfRange(deviceData,34,38);
                    final float result = getFloat(myData);
                    Log.i(TAG,Bytes2HexString(myData,0,myData.length)) ;
                    Log.i(TAG,"float:"+" "+ result);

                    postMainThread(new Runnable() {
                        @Override
                        public void run() {
                            if(mClassicDeviceCallback == null){
                                return;
                            }
                            mClassicDeviceCallback.onResult(BTBioHermesDevice.this,result);
                        }
                    });
                }

                mRxLock.writeLock().unlock();
            } catch (Exception e) {
                Log.e(TAG,"error"+e);
                mRxLock.writeLock().lock();
                mResult = -1;
                mRecvThread = null;
                os = null;
                is = null;
                mSocket = null;
                mRxLock.writeLock().unlock();
                over();
            }
        }
    }

    public static float getFloat(byte[] b) {
        int accum = 0;
        accum = accum|(b[0] & 0xff) << 0;
        accum = accum|(b[1] & 0xff) << 8;
        accum = accum|(b[2] & 0xff) << 16;
        accum = accum|(b[3] & 0xff) << 24;
        System.out.println(accum);
        return Float.intBitsToFloat(accum);
    }

    public static String Bytes2HexString(byte[] b, int start, int len) {
        String ret = "";
        for (int i = start; i < len; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase()+" ";
        }
        return ret;
    }

    public static boolean isTransferFin(byte[] data){
        if(data.length != 6) {
            return false;
        }

        int[] finishCmd = {0x48,0x42,0x06,0x00,0x00,0x90};
        for(int i=0;i<6;i++){
            int translateA = byteToInt(data[i]);
            if(translateA != finishCmd[i]){
                return false;
            }
        }

        return true;
    }


    public static int byteToInt(byte a){
        return a&0xff;
    }

//    BTCSFZReaderDevice mDevice = this;

}
