
package com.tydic.idreader;

import android.annotation.SuppressLint;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.util.Log;

import com.alibaba.fastjson.JSONException;
import com.ctsi.idcertification.BtReaderClient;
import com.ctsi.idcertification.CloudReaderClient;
import com.ctsi.idcertification.constant.Constant;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.tydic.idreader.utils.Des33;
import com.tydic.idreader.utils.ObjectUtil;

import org.jarjar.apache.commons.codec.digest.DigestUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.annotation.Nullable;

public class RNIdreaderModule extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;

    private CloudReaderClient reader;

    private BtReaderClient bt_reader;

    private BluetoothHelper mBluetoothHelper;

    private NFCHelper mNFCHelper;

    private ExecutorService pool = Executors.newCachedThreadPool();

    private String timestamp = "";

    private String appSecret; // appId对应的加密密钥
    private String businessExt;
    private StringBuffer sbData = new StringBuffer();
    private String appId;
    private String nonce;
    private String signature = "";
    private String appSecret_3des; // appId对应的加密密钥

    /**
     * 蓝牙设备
     */
    private List<BluetoothDeviceBean> deviceList = new ArrayList<>();


    public RNIdreaderModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
        mBluetoothHelper = new BluetoothHelper(reactContext);
        mNFCHelper = new NFCHelper(reactContext);
    }

    @Override
    public String getName() {
        return "RNIdreader";
    }

    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put(Config.BLUETOOTH_SUPPORT, mBluetoothHelper.isSupportBluetooth());
        constants.put(Config.NFC_SUPPORT, mNFCHelper.isSupportNfc());
        return constants;
    }

    /**
     * 蓝牙是否开启
     * @param callback
     */
    @ReactMethod
    public void isBluetoothEnabled(Callback callback){
        callback.invoke(mBluetoothHelper.isEnabled());
    }

    /**
     * NFC是否开启
     * @param callback
     */
    @ReactMethod
    public void isNFCEnabled(Callback callback){
        callback.invoke(mNFCHelper.isEnabled());
    }

    /**
     * 设置蓝牙
     */
    @ReactMethod
    public void settingBluetooth() {
        if (mBluetoothHelper.isSupportBluetooth()) {
            mBluetoothHelper.settingBluetooth(getCurrentActivity());
        }
    }

    /**
     * 强制打开蓝牙
     */
    @ReactMethod
    public void openBluetooth(Callback callback) {
        if (mBluetoothHelper.isSupportBluetooth() && !mBluetoothHelper.isEnabled()){
            boolean status = mBluetoothHelper.mBluetoothAdapter.enable();
            callback.invoke(status);
        }else {
            callback.invoke(false);
        }
    }

    /**
     * 设置NFC
     */
    @ReactMethod
    public void settingNFC() {
        try {
            mNFCHelper.settingNFC(getCurrentActivity());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 已经配对的设备（与SDK无关，只要蓝牙开启即可获取配对蓝牙设备）
     */
    @ReactMethod
    public void getBondedDevices(Callback callback) {
        try {
            if (mBluetoothHelper.isEnabled()) {
                List<BluetoothDeviceBean> devices = mBluetoothHelper.getBondedDevices();
                if (devices != null) {
                    callback.invoke(true, ObjectUtil.listToArray(devices));
                } else {
                    callback.invoke(true, Arguments.createArray());
                }
            } else {
                callback.invoke(false, "请先检测蓝牙是否开启");
            }
        } catch (JSONException e) {
            callback.invoke(false, e.toString());
        }
    }

    /**
     * 停止扫描
     */
    @ReactMethod
    public void stopScan(){
        if (mBluetoothHelper != null){
            mBluetoothHelper.cancelScan();
        }
    }

    /**
     * 扫描蓝牙设备
     */
    @ReactMethod
    public void scanBluetooth() {
        deviceList.clear();
        if (mBluetoothHelper.isEnabled()) {
            //添加已配对设备
            List<BluetoothDeviceBean> devices = mBluetoothHelper.getBondedDevices();
            deviceList.addAll(devices);
            if (deviceList.size() > 0) {
                //扫描到有已配对设备，先回调数据一次
                reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                        .emit(Config.BLUETOOTH_LISTENER, ObjectUtil.arrayToMap(true, Config.SCANING, deviceList));
            }
            mBluetoothHelper.scanBluetoothDevices(new OnBluetoothScanListener() {
                @Override
                public void onResult(BluetoothDeviceBean device) {
                    removeRepeat(deviceList, device);
                    reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                            .emit(Config.BLUETOOTH_LISTENER, ObjectUtil.arrayToMap(true, Config.SCANING, deviceList));
                }

                @Override
                public void onFinish() {
                    reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                            .emit(Config.BLUETOOTH_LISTENER, ObjectUtil.arrayToMap(true, Config.SCANED, deviceList));
                }
            });
        } else {
            reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                    .emit(Config.BLUETOOTH_LISTENER, ObjectUtil.arrayToMap(false, Config.SCANED, deviceList));
        }
    }

    /**
     * 添加设备时检测重复的蓝牙设备
     *
     * @param list
     * @param bean
     */
    private void removeRepeat(List<BluetoothDeviceBean> list, BluetoothDeviceBean bean) {
        String address = bean.getAddress();
        boolean isHava = false;
        for (BluetoothDeviceBean device : list) {
            if (device.getAddress().equals(address)) {
                isHava = true;
            }
        }
        if (!isHava) {
            list.add(bean);
        }
    }

    /**
     * 注册蓝牙
     *
     * @param appId
     * @param appSecret
     * @param appSecret_3des
     * @param nonce
     * @param businessExt
     */
    @ReactMethod
    public void registerApp(String appId, String appSecret, String appSecret_3des, String nonce, String businessExt) {
        this.appId = appId;
        this.appSecret = appSecret;
        this.appSecret_3des = appSecret_3des;
        this.nonce = nonce;
        this.businessExt = businessExt;
        reader = new CloudReaderClient(getCurrentActivity());
        bt_reader = new BtReaderClient(getCurrentActivity());

    }

    /**
     * 蓝牙读卡
     *
     * @param address
     * @param callback
     */
    @ReactMethod
    public void readCard(String address, final Callback callback) {
        if (bt_reader == null) {
            callback.invoke(false, "请先调用registerApp方法");
        } else {
            if (!mBluetoothHelper.isSupportBluetooth()) {
                callback.invoke(false, "设备不支持蓝牙");
            } else if (!mBluetoothHelper.isEnabled()) {
                callback.invoke(false, "设备蓝牙未开启");
            } else {
                //设置蓝牙状态回调
                bt_reader.setCallBack(new BtReaderClient.IClientCallBack() {
                    @Override
                    public void onBtState(boolean b) {
                        if (b) {
                            read(Config.BLUETOOTH_READ, null);
                        } else {
                            //蓝牙断开
                            callback.invoke(false, "蓝牙已经断开");
                        }
                    }
                });
                boolean isSuccess = bt_reader.connectBt(address);
                if (isSuccess) {
                    callback.invoke(true, "可以使用蓝牙读取信息");
                }else {
                    callback.invoke(false, "蓝牙连接失败");
                }
            }
        }
    }

    @SuppressLint("NewApi")
    @ReactMethod
    public void readNFC(Callback callback) {
        if (reader == null) {
            callback.invoke(false, "请先调用registerApp方法");
        } else {
            if (!mNFCHelper.isSupportNfc()) {
                callback.invoke(false, "设备不支持NFC");
            } else if (!mNFCHelper.isEnabled()) {
                callback.invoke(false, "设备NFC未开启");
            } else {
                callback.invoke(true, "可以使用NFC读取信息");
                reader.disconnect();
                reader.connect(Constant.READER_TYPE_NFC, new NfcAdapter.ReaderCallback() {
                    @Override
                    public void onTagDiscovered(final Tag tag) {
                        if (tag != null) {
                            mNFCHelper.nfcAdapter.disableForegroundDispatch(getCurrentActivity());
                        }
                        read(Config.NFC_READ, tag);
                    }
                });
            }
        }
    }

    /**
     * 加密字符串
     *
     * @return
     */
    private String getSignature() {
        timestamp = System.currentTimeMillis() + "";
        sbData = new StringBuffer();
        sbData.append(appId).append(appSecret).append(businessExt)
                .append(nonce).append(timestamp);
        return DigestUtils.shaHex(sbData.toString());
    }

    /**
     * 读取设备  0-蓝牙  1-NFC
     *
     * @param type
     */
    private void read(final int type, final Tag tag) {
        signature = getSignature();

        pool.execute(new Runnable() {
            @Override
            public void run() {
                Map result;
                String resultType;
                if (type == Config.BLUETOOTH_READ) {
                    resultType = Config.BLUETOOTH_CALLBACK;
                    result = bt_reader.cloudReadCert(appId, timestamp, nonce, businessExt, signature);
                } else {
                    Log.d("NFC的Tag", tag.toString());
                    resultType = Config.NFC_CALLBACK;
                    result = reader.CloudReadCert(appId, timestamp, nonce, businessExt, signature, Constant.READER_TYPE_NFC, tag);
                    Log.d("NFC的result", result.toString());
                }
                if (result != null) {
                    System.out.println("扫描结果成功="+result.toString());
                    int resultCode = Integer.valueOf(result.get(Constant.RESULT_MAP_KEY_FLAG).toString());
                    String stepFlag = result.get(Constant.STEP_MAP_KEY_FLAG) + "";
                    Log.d("扫描结果=", result.toString());
                    if (resultCode == Constant.RESULT_OK) {
                        //成功
                        try {
                            Object msg = result.get(Constant.RESULT_MAP_KEY_ERRORMESSAGE);
                            String errMsg = "";
                            if (msg != null){
                                errMsg = (String) msg;
                            }
                            String content = (String) result.get(Constant.RESULT_MAP_KEY_CONTENT);
                            String contentDecryp = Des33.decode1(content, appSecret_3des);
                            //获取XML的map对象
                            WritableMap xmlMap = ObjectUtil.xmlStr2Map(contentDecryp);
                            xmlMap.putInt("resultFlag", resultCode);
                            xmlMap.putString("stepFlag", stepFlag);
                            WritableMap resultMap = ObjectUtil.emitterCallback(true, resultType, errMsg, xmlMap);
                            System.out.println("扫描结果成功resultMap="+resultMap.toString());
                            reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(Config.BLUETOOTH_LISTENER, resultMap);
                            Log.d("扫描结果成功=", "stepFlag:" + stepFlag + "\n" + "resultContent:\n" + contentDecryp);
                        } catch (Exception e) {
                            System.out.println("扫描结果成功中的失败="+e.toString());
                            //返回结果为空
                            WritableMap resultMap = ObjectUtil.emitterCallback(false, resultType, "异常错误", Arguments.createMap());
                            reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(Config.BLUETOOTH_LISTENER, resultMap);
                            e.printStackTrace();
                        }
                    } else {
                        //失败
                        try {
                            String errMsg = (String) result.get(Constant.RESULT_MAP_KEY_ERRORMESSAGE);
                            WritableMap map = Arguments.createMap();
                            map.putInt("resultFlag", resultCode);
                            map.putString("stepFlag", stepFlag);
                            WritableMap resultMap = ObjectUtil.emitterCallback(false, resultType, errMsg, map);
                            reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(Config.BLUETOOTH_LISTENER, resultMap);
                            Log.d("扫描结果失败=", errMsg);
                        } catch (Exception e) {
                            //返回结果为空
                            WritableMap resultMap = ObjectUtil.emitterCallback(false, resultType, "异常错误", Arguments.createMap());
                            reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(Config.BLUETOOTH_LISTENER, resultMap);
                            e.printStackTrace();
                        }
                    }

                } else {
                    //返回结果为空
                    System.out.println("扫描结果失败="+"没有数据返回");
                    Log.d("扫描结果失败=", "没有数据返回");
                    WritableMap resultMap = ObjectUtil.emitterCallback(false, resultType, "未获取到任何数据", Arguments.createMap());
                    reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(Config.BLUETOOTH_LISTENER, resultMap);
                }
            }
        });
    }

}