package cn.fits.plugins.pda;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import com.getcapacitor.Bridge;
import com.getcapacitor.JSObject;
import com.zebra.rfid.api3.ACCESS_OPERATION_CODE;
import com.zebra.rfid.api3.ACCESS_OPERATION_STATUS;
import com.zebra.rfid.api3.Antennas;
import com.zebra.rfid.api3.ENUM_TRANSPORT;
import com.zebra.rfid.api3.ENUM_TRIGGER_MODE;
import com.zebra.rfid.api3.HANDHELD_TRIGGER_EVENT_TYPE;
import com.zebra.rfid.api3.INVENTORY_STATE;
import com.zebra.rfid.api3.InvalidUsageException;
import com.zebra.rfid.api3.OperationFailureException;
import com.zebra.rfid.api3.RFIDReader;
import com.zebra.rfid.api3.ReaderDevice;
import com.zebra.rfid.api3.Readers;
import com.zebra.rfid.api3.RfidEventsListener;
import com.zebra.rfid.api3.RfidReadEvents;
import com.zebra.rfid.api3.RfidStatusEvents;
import com.zebra.rfid.api3.SESSION;
import com.zebra.rfid.api3.SL_FLAG;
import com.zebra.rfid.api3.START_TRIGGER_TYPE;
import com.zebra.rfid.api3.STATUS_EVENT_TYPE;
import com.zebra.rfid.api3.STOP_TRIGGER_TYPE;
import com.zebra.rfid.api3.TagData;
import com.zebra.rfid.api3.TriggerInfo;

import java.util.ArrayList;

public class ZebraPDA {

    private static Readers readers;//读卡器列表
    private static ArrayList<ReaderDevice> availableRFIDReaderList;
    private static ReaderDevice readerDevice;
    private static RFIDReader reader;
    String readerName = "RFD4031-G10B700-JP";
    private EventHandler eventHandler;
    private int MAX_POWER = 270;
    Bridge myBridge;
    // 初始化
    public Boolean initRFID(Context c, Bridge bridge) {
        myBridge =bridge;
        Boolean isConnect = false;
        readers = new Readers(c, ENUM_TRANSPORT.ALL);// 获取所有设备
        try {
            if (readers.GetAvailableRFIDReaderList() != null) {
                availableRFIDReaderList = readers.GetAvailableRFIDReaderList();
                if (availableRFIDReaderList.size() != 0) {
                    // if single reader is available then connect it
                    if (availableRFIDReaderList.size() == 1) {// 通常只有一个
                        readerDevice = availableRFIDReaderList.get(0);
                        reader = readerDevice.getRFIDReader();// 获取扫码枪的实例
                        if (reader != null){
                            isConnect= connect();
                        }
                    } else {
                        // search reader specified by name
                        for (ReaderDevice device : availableRFIDReaderList) {
                            if (device.getName().equals(readerName)) {
                                readerDevice = device;
                                reader = readerDevice.getRFIDReader();
                            }
                        }
                    }
                }
            }
        } catch (InvalidUsageException e) {
            e.printStackTrace();
        }
        return isConnect;
    }

    // 执行连接
    private synchronized Boolean connect() {
        Log.d("TAG", "connect " + reader.getHostName());
        try {
            if (!reader.isConnected()) {
                // Establish connection to the RFID Reader
                reader.connect();// 扫码枪获取执行连接方法
                ConfigureReader();
                if(reader.isConnected()){// 连接成功相当语是initUHF
                    Log.d("TAG", "Connected " + reader.getHostName());
                    return true;
                }
            }
        } catch (InvalidUsageException e) {
            e.printStackTrace();
        } catch (OperationFailureException e) {
            e.printStackTrace();
            Log.d("TAG", "OperationFailureException " + e.getVendorMessage());
            String des = e.getResults().toString();
            Log.d("TAG", "Connection failed " +  e.getVendorMessage() + " " + des);
            return false;
        }
        return false;
};

// 连接配置
private void ConfigureReader() {
    Log.d("TAG", "ConfigureReader " + reader.getHostName());
    if (reader.isConnected()) {
        TriggerInfo triggerInfo = new TriggerInfo();
        triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE);
        triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_IMMEDIATE);
        try {
            // receive events from reader
            if (eventHandler == null)
                eventHandler = new EventHandler();
            reader.Events.addEventsListener(eventHandler);
            // HH event
            reader.Events.setHandheldEvent(true);
            // tag event with tag data
            reader.Events.setTagReadEvent(true);
            reader.Events.setAttachTagDataWithReadEvent(false);
            // set trigger mode as rfid so scanner beam will not come
            reader.Config.setTriggerMode(ENUM_TRIGGER_MODE.RFID_MODE, true);
            // set start and stop triggers
            reader.Config.setStartTrigger(triggerInfo.StartTrigger);
            reader.Config.setStopTrigger(triggerInfo.StopTrigger);
            // power levels are index based so maximum power supported get the last one
            MAX_POWER = reader.ReaderCapabilities.getTransmitPowerLevelValues().length - 1;//返回传输功率电平值 相当于getRFIDPower
            // set antenna configurations
            Antennas.AntennaRfConfig config = reader.Config.Antennas.getAntennaRfConfig(1);
            config.setTransmitPowerIndex(MAX_POWER);// 设置功率 相当于setRFIDPower
            config.setrfModeTableIndex(0);
            config.setTari(0);
            reader.Config.Antennas.setAntennaRfConfig(1, config);
            // Set the singulation control
            Antennas.SingulationControl s1_singulationControl = reader.Config.Antennas.getSingulationControl(1);
            s1_singulationControl.setSession(SESSION.SESSION_S0);
            s1_singulationControl.Action.setInventoryState(INVENTORY_STATE.INVENTORY_STATE_A);
            s1_singulationControl.Action.setSLFlag(SL_FLAG.SL_ALL);
            reader.Config.Antennas.setSingulationControl(1, s1_singulationControl);
            // delete any prefilters
            reader.Actions.PreFilters.deleteAll();
            //
        } catch (InvalidUsageException | OperationFailureException e) {
            e.printStackTrace();
        }
    }
}

// 事件监听
public class EventHandler implements RfidEventsListener {
    // Read Event Notification
    public void eventReadNotify(RfidReadEvents e) {
        // Recommended to use new method getReadTagsEx for better performance in case of large tag population
        TagData[] myTags = reader.Actions.getReadTags(100);// 获取标签id 相当于 readTagFromBuffer
        if (myTags != null) {
            for (int index = 0; index < myTags.length; index++) {
                Log.d("TAG", "Tag ID " + myTags[index].getTagID());
                if (myTags[index].getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ &&
                        myTags[index].getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                    if (myTags[index].getMemoryBankData().length() > 0) {
                        Log.d("TAG", " Mem Bank Data " + myTags[index].getMemoryBankData());
                    }
                }
                if (myTags[index].isContainsLocationInfo()) {
                    short dist = myTags[index].LocationInfo.getRelativeDistance();
                    Log.d("TAG", "Tag relative distance " + dist);
                }
            }
            // possibly if operation was invoked from async task and still busy
            // handle tag data responses on parallel thread thus THREAD_POOL_EXECUTOR
            new AsyncDataUpdate().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, myTags);
        }
    }

    // Status Event Notification
    public void eventStatusNotify(RfidStatusEvents rfidStatusEvents) {
        Log.d("TAG", "Status Notification: " + rfidStatusEvents.StatusEventData.getStatusEventType());
        if (rfidStatusEvents.StatusEventData.getStatusEventType() == STATUS_EVENT_TYPE.HANDHELD_TRIGGER_EVENT) {//发生了手持式喷枪/按钮事件“拉动/释放”。
            if (rfidStatusEvents.StatusEventData.HandheldTriggerEventData.getHandheldEvent() == HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED) {//拉动
                new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... voids) {
//                            context.handleTriggerPress(true);
                        performInventory();
                        return null;
                    }
                }.execute();
            }
            if (rfidStatusEvents.StatusEventData.HandheldTriggerEventData.getHandheldEvent() == HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_RELEASED) {//释放
                new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... voids) {
                        stopInventory();
                        return null;
                    }
                }.execute();
            }
        }
    }
}

private class AsyncDataUpdate extends AsyncTask<TagData[], Void, Void> {
    @Override
    protected Void doInBackground(TagData[]... params) {
        handleTagdata(params[0]);
        return null;
    }
}
// 处理扫到的数据
public void handleTagdata(TagData[] tagData) {
    final StringBuilder sb = new StringBuilder();
    for (int index = 0; index < tagData.length; index++) {
        sb.append(tagData[index].getTagID());
    }
    String tagID = hexStringToAsciiString(sb.toString());
    Log.d("TAG", "tagID=" + tagID);
    JSObject ret = new JSObject();
    ret.put("tagID", tagID);
    myBridge.triggerJSEvent("ZebraNotify", "window", String.valueOf(ret));
}

    public static String hexStringToAsciiString(String hex) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hex.length() - 1; i += 2) {
            String s = hex.substring(i, i + 2);
            sb.append((char) Integer.parseInt(s, 16));
        }
        return sb.toString().trim();
    }

// 开启读卡
synchronized void performInventory() {
    // check reader connection
    if (!isReaderConnected())
        return;
    try {
        reader.Actions.Inventory.perform();
    } catch (InvalidUsageException e) {
        e.printStackTrace();
    } catch (OperationFailureException e) {
        e.printStackTrace();
    }
}

// 停止读取
synchronized void stopInventory() {
    // check reader connection
    if (!isReaderConnected())
        return;
    try {
        reader.Actions.Inventory.stop();
    } catch (InvalidUsageException e) {
        e.printStackTrace();
    } catch (OperationFailureException e) {
        e.printStackTrace();
    }
}
// 判断是否连接成功
private boolean isReaderConnected() {
    if (reader != null && reader.isConnected())
        return true;
    else {
        Log.d("TAG", "reader is not connected");
        return false;
    }
}
    // 关闭当前读卡器连接
    public synchronized void disconnect() {
        Log.d("TAG", "disconnect " + reader);
        try {
            if (reader != null) {
                reader.Events.removeEventsListener(eventHandler);
                reader.disconnect();
            }
        } catch (InvalidUsageException e) {
            e.printStackTrace();
        } catch (OperationFailureException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 关闭所有读卡器
    public synchronized void dispose() {
        try {
            if (readers != null) {
                reader = null;
                readers.Dispose();
                readers = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
