package cordova.plugin.uhfr;

import android.os.Message;
import android.util.Log;
import cn.pda.serialport.Tools;
import com.handheld.uhfr.UHFRManager;
import com.uhf.api.cls.Reader;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.*;


/**
 * 超高频（UHF）读写卡插件。
 * 因不同的机型使用的so库不同，故无法适配所有机型。
 */
public class UHFR extends CordovaPlugin {
    private UHFRManager manager;
    private String selectedEpc = "";
    private byte[] password = Tools.HexString2Bytes("00000000");
    private boolean threadFlag;

    @Override
    protected void pluginInitialize() {
        super.pluginInitialize();
        manager = UHFRManager.getInstance();
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        switch (action) {
            case "readCard":
                this.readCard(callbackContext);
                return true;
            case "searchCard":
                this.searchCard(callbackContext);
                return true;
            case "stopSearchCard":
                this.stopSearchCard(callbackContext);
                return true;
            case "writeCard":
                this.writeCard(args, callbackContext);
                return true;
            case "setPower":
                this.setPower(args, callbackContext);
                return true;
            case "startWork":
                this.startWork(callbackContext);
                return true;
            case "endWork":
                this.endWork(callbackContext);
                return true;
            case "selectCard":
                this.selectCard(args, callbackContext);
                break;
            case "inventoryCard":
                this.inventoryCard(callbackContext);
                return true;
            case "stopInventoryCard":
                this.stopInventoryCard(callbackContext);
                return true;
        }
        return false;
    }


    private void startWork(CallbackContext callbackContext) {
        if (this.manager == null) {
            manager = UHFRManager.getInstance();
        }
        callbackContext.success();
    }

    private void endWork(CallbackContext callbackContext) {
        if (this.manager != null) {
            this.manager.close();
            this.manager = null;
        }
        callbackContext.success();
    }


    private void stopInventoryCard(CallbackContext callbackContext) {
        threadFlag = false;
        manager.asyncStopReading();
        callbackContext.success("停止");
    }

    private void inventoryCard(CallbackContext callbackContext) {
        threadFlag = true;
        manager.asyncStartReading();
        Thread thread = new InventoryThread(callbackContext);
        thread.start();
    }


    /**
     * 巡卡，每执行一次，就扫描一次范围内的卡片，将巡到的卡片信息以json数组的形式返回
     */
    private void searchCard(CallbackContext callbackContext) {
        manager.asyncStartReading();
        try {
            Thread.sleep(100);
            JSONArray ja = onceSearchCard();
            manager.asyncStopReading();
            callbackContext.success(ja);
        } catch (Exception e) {
            callbackContext.error(e.getMessage());
        }
    }

    private JSONArray onceSearchCard() throws JSONException {
        List<Reader.TAGINFO> list1;
        list1 = manager.tagInventoryRealTime();
        String data;
        JSONArray ja = new JSONArray();
        JSONObject jo;
        if (list1 != null && list1.size() > 0) {
            for (Reader.TAGINFO tfs : list1) {
                jo = new JSONObject();
                byte[] epcdata = tfs.EpcId;
                data = Tools.Bytes2HexString(epcdata, epcdata.length);
                int rssi = tfs.RSSI;
                jo = new JSONObject();
                jo.put("mEpcBytes", data);
                jo.put("mRssi", rssi);
                ja.put(jo);
            }
        }
        return ja;
    }

    private class InventoryThread extends Thread {

        private CallbackContext cb;

        public InventoryThread(CallbackContext cb) {
            super();
            this.cb = cb;
        }

        public InventoryThread() {
            super();
        }

        @Override
        public void run() {
            super.run();
            try {
                while (threadFlag) {
                    JSONArray ja = onceSearchCard();
                    PluginResult pr = new PluginResult(PluginResult.Status.OK, ja);
                    pr.setKeepCallback(true);
                    cb.sendPluginResult(pr);
                    Thread.sleep(100);
                }
            } catch (Exception e) {
                cb.error(e.getMessage());
            }
        }
    }

    private void stopSearchCard(CallbackContext callbackContext) {
        manager.asyncStopReading();
        callbackContext.success("巡卡停止");
    }

    /**
     * 读卡，将USER区的hex字符串转换为ascii读取，因EPC区与TID区不能写入，故暂时只读取USER区，注释掉的部分为适应EPC区与TID区读取的代码
     * 将注释解开后应抛出JSONException
     */
    private void readCard(CallbackContext callbackContext) {
//    JSONObject obj = message.getJSONObject(0);
//    int site = obj.getInt("site");
//    int addr = obj.getInt("addr");
//    if (site == 1) {
//      addr = 2;
//      length = 6;
//    } else if (site == 3) {
//      addr = 0;
//      length = 32;
//    } else if (site == 2) {
//      addr = 0;
//      length = 12;
//    }
//        manager.selectEPC(Tools.HexString2Bytes(this.selectedEpc));
        int length = 32;
//        byte[] data = manager.readFrom6C(3, 0, length, password);
        byte[] data = new byte[length * 2];
        if (this.selectedEpc.length() == 0) {
            manager.getTagData(3, 0, length, data, password, (short) 1000);
        } else {
            data = manager.getTagDataByFilter(3, 0, length, password, (short) 1000, Tools.HexString2Bytes(this.selectedEpc), 1, 0, true);
        }
        if (data != null && data.length >= 1) {
            String msg;
//      if (site == 3) {   // 读取User区的时候，将16进制字符串转换为ascii
            msg = Util.bytes2Str(data);
//      } else { // 因EPC区与TID区不能写入，故读取时不转码
//        msg = Tools.Bytes2HexString(data, data.length);
//      }
            callbackContext.success(msg);
        } else {
            callbackContext.error("读取失败");
        }
    }

    /**
     * 选卡，将选到的卡储存在this.selectedEpc中
     */
    private void selectCard(JSONArray message, CallbackContext callbackContext) throws JSONException {
        JSONObject obj = message.getJSONObject(0);
        String epc = obj.getString("epc");
//        manager.selectEPC(Tools.HexString2Bytes(epc));
        this.selectedEpc = epc;
        callbackContext.success();
    }

    /**
     * 写卡，将ascii转换为bytes并写入
     */
    private void writeCard(JSONArray message, CallbackContext callbackContext) {
//        manager.selectEPC(Tools.HexString2Bytes(this.selectedEpc));
        String _data = null;
        try {
            JSONObject obj = message.getJSONObject(0);
            _data = Util.str2HexStr(obj.getString("data"));
        } catch (JSONException e) {
            callbackContext.error("JSON解析失败");
        }
        // 处理_data，将ascii转换为16进制字符串，超过32 * 4位的16进制字符串报错，小于32 * 4时在16进制字符串末位补0x00作为完结标记，再转换为bytes
        if (_data != null && _data.length() > 32 * 4) {
            callbackContext.error("数据过长");
            return;
        }
        if (_data.length() < 32 * 4) {
            _data += "00";
        }
        byte[] dataBytes = Util.hexStringToBytes(_data);
        boolean writeFlag = false;
        Reader.READER_ERR er = null;
        if (dataBytes != null) {
            if (this.selectedEpc.length() > 0) {
                er = manager.writeTagDataByFilter((char) 3, 0, dataBytes, dataBytes.length / 2, password, (short) 1000, Tools.HexString2Bytes(this.selectedEpc), 1, 0, true);
            } else {
                er = manager.writeTagData((char) 3, 0, dataBytes, dataBytes.length / 2, password, (short) 1000);
            }
//      writeFlag = manager.writeTo6C(password, 3, 0, dataBytes.length / 2, dataBytes);
        }
        if (er == Reader.READER_ERR.MT_OK_ERR) {
            callbackContext.success("写入成功");
        } else {
            callbackContext.error("写入失败");
        }
    }

    private void setPower(JSONArray message, CallbackContext callbackContext) throws JSONException {
        int power = message.getInt(0);
        if (power > 30) {
            power = 30;
        } else if (power < 5) {
            power = 5;
        }
        Reader.READER_ERR err = manager.setPower(power, power);
        if (err == Reader.READER_ERR.MT_OK_ERR) {
            callbackContext.success("设置成功");
        } else {
            callbackContext.error("设置失败");
        }
    }

    @Override
    public void onDestroy() {
        if (this.manager != null) {
            this.manager.close();
        }
    }
}
