package com.unis.crk.hardware.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.rfid.CReader;
import com.rfid.ReadTag;
import com.rfid.ReaderParameter;
import com.rfid.TagCallback;
import com.unis.crk.cplbusiness.entity.DataCrkywCplbjdyDefault;
import com.unis.crk.cplbusiness.service.IDataCrkywCplbjdyDefaultService;
import com.unis.crk.cplbusiness.service.impl.DataCrkywCplbjdyDefaultServiceImpl;
import dm.jdbc.filter.stat.json.JSONArray;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.core.AbstractDestinationResolvingMessagingTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @类名: RfidService
 * @描述：RFID设备功能实现类 部分错误代码：0：操作成功；-1：未连接读写器；-2：不存在的epc;-3:发生异常错误
 * @作者：zc
 * @日期：2022/7/6
 * @版本：1.0
 */


public class Rfid3Service {
    public static List<ReadTag> lsTagList = new ArrayList<ReadTag>();
    public static List<String> epcList =new ArrayList<String>();
    public static  String id=null;
    byte[] PASS_WD = new byte[4];
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public Rfid3Service(){
        //密码用默认的
        PASS_WD[0] = 0;
        PASS_WD[1] = 0;
        PASS_WD[2] = 0;
        PASS_WD[3] = 0;
    }
    private static int MAX_LENGTH = 16;
    private boolean isConn;
    CReader reader;
    public static Map<String, Object> data=new HashMap<String, Object>();
    public static Map<String, Map<String, String>> datarfid=new HashMap<String,Map<String, String>>();
    public Map<String, Object> getData(){
        return data;
    }
    public Map<String, Map<String, String>> getDatarfid(){
        return datarfid;
    }
    /**
     * 回调函数，并发布mq信息
     */
    public class MsgCallback implements TagCallback {
        private RabbitTemplate rabbitTemplate = BeanUtils.getBean(RabbitTemplate.class);
        private DataCrkywCplbjdyDefaultServiceImpl bq = BeanUtils.getBean(DataCrkywCplbjdyDefaultServiceImpl.class);
        private String convertHexToString(String hex){
            StringBuilder sb = new StringBuilder();
            StringBuilder temp = new StringBuilder();
            //49204c6f7665204a617661 split into two characters 49, 20, 4c...
            for( int i=0; i<hex.length()-1; i+=2 ){
                //grab the hex in pairs
                String output = hex.substring(i, (i + 2));
                //convert hex to decimal
                if(output.equals("00"))
                    break;
                int decimal = Integer.parseInt(output, 16);
                //convert the decimal to character
                sb.append((char)decimal);
                temp.append(decimal);
            }
            return sb.toString();
        }

        @Override
        public void tagCallback(ReadTag arg0) {
            //根据厂家技术的说法，在寻卡成功后才会触发回调，返回标签epc等数据
            String epc = arg0.epcId.toUpperCase();
            if (epcList.indexOf(epc) == -1) {
                    epcList.add(epc);
                    lsTagList.add(arg0);
            }
            if(StrUtil.isNotBlank(id) && epcList.size()>0){
                for(int k=0;k<epcList.size();k++){
                    String e = epcList.get(k);
                    String s = convertHexToString(e);
                    DataCrkywCplbjdyDefault oneBybh=null;
                    try {
                         oneBybh = bq.getOneBybh(s);
                    } catch (Exception f) {
                        f.printStackTrace();
                        System.out.println(f);
                    }
                    if(oneBybh !=null){
                    String spmcbh = oneBybh.getSjjlspmcbh();
                    Double js = oneBybh.getJs();
                        HashMap<String, String> stringStringHashMap = new HashMap<>();
                        stringStringHashMap.put(e,spmcbh+"|"+js);
                        Map<String, Map<String, String>> datarfid = getDatarfid();
                        if(ObjectUtil.isNotNull(datarfid.get(id))){
                            Map<String, String> stringDoubleMap = datarfid.get(id);
                            stringDoubleMap.putAll(stringStringHashMap);
                        }else{
                            Rfid3Service.datarfid.put(id,stringStringHashMap);
                        }

                        System.out.println(Rfid3Service.datarfid.toString());
                    }else{
                        HashMap<String, String> stringStringHashMap = new HashMap<>();
                        stringStringHashMap.put(e,"该标签未查询到商品");
                        Map<String, Map<String, String>> datarfid = getDatarfid();
                        if(ObjectUtil.isNotNull(datarfid.get(id))){
                            Map<String, String> stringDoubleMap = datarfid.get(id);
                            stringDoubleMap.putAll(stringStringHashMap);
                        }else{
                            Rfid3Service.datarfid.put(id,stringStringHashMap);
                        }
                        System.out.println(Rfid3Service.datarfid.toString());
                    }
                }
                //rabbitTemplate.convertAndSend("inOutLib.exchange", "inOutLib.uploadData", systemlog.uploadName());
                /*Queue queue = new Queue("rfid."+id, false,false,true);
                String s = JSONUtil.toJsonStr(data);
                rabbitTemplate.convertAndSend("inOutLib.exchange", "rfid."+id, s);*/

            }


        }

    };



        /**
         * 链接rfid
         * @param ipAddr ip地址
         * @param port 端口号
         * @return
         */
    public int connect(String ipAddr, int...port){
        //disConnect();
        String timeStr1 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println("开始连接的时间：" + timeStr1);
        reader = new CReader(ipAddr,port.length == 0?27011 : port[0],0);
        int result = reader.Connect();
        isConn = result == 0 ? true : false;
        if(isConn){
            byte[]Version=new byte[2];
            byte[]Power=new byte[1];
            byte[]band=new byte[1];
            byte[]MaxFre=new byte[1];
            byte[]MinFre=new byte[1];
            byte[]BeepEn=new byte[1];
            byte[]Ant=new byte[1];
            int rst = reader.GetUHFInformation(Version, Power, band, MaxFre, MinFre, BeepEn, Ant);
            isConn = rst == 0 ? true : false;
            if(isConn){
                if(BeepEn[0]==0)//如果蜂鸣器没有打开，则开蜂鸣器
                    reader.SetBeepNotification(1);
            }
        }
        String timeStr2 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println("连接完成时间：" + timeStr2);
        return result;
    }

        /**
         *设置读写器功率
         * @param power 读写器的输出功率。范围是0到30，单位dBm。
         * @param saveCfg false表示调电不保存；true表示掉电保存
         * @return
         */
    public int SetRfPower(int power, boolean...saveCfg){
        if(!isConn)
            return -1;

        return reader.SetRfPower(power | (saveCfg.length == 0 || saveCfg[0] ? 256 : 128));  //或256，设置后保存，或128，设置后不保存
    }

        /**
         * 设置读写器的有效工作天线
         * @param ant1
         * @param ant2
         * @param ant3
         * @param ant4
         * @return
         */
    public int setAntenna(boolean ant1, boolean ant2, boolean ant3, boolean ant4){
        if(!isConn)
            return -1;

        byte ant = 0x00;
        if(ant1) {
            ant = (byte) (ant | 1);
        }
        if(ant2) {
            ant = (byte) (ant | 2);
        }
        if(ant3) {
            ant = (byte) (ant | 4);
        }
        if(ant4) {
            ant = (byte) (ant | 8);
        }
        int result = reader.SetAntenna(ant);
        return result;
    }

    public void setWRTime(int duration){
        //TODO 该功能待完善
    }

    public int queryLabel(){
        if(!isConn)
            return -1;

        ReaderParameter param = reader.GetInventoryPatameter();
        param.SetSession(0);//设置Session
        param.SetQValue(4);//设置QValue
//				param.SetAntenna(1);//读TID;
        reader.SetInventoryPatameter(param);
        MsgCallback callback = new MsgCallback();
        reader.SetCallBack(callback);
        reader.StartRead();
        try {
            Thread.sleep(100);
            reader.StopRead();
            Thread.sleep(1000);
        }catch(Exception e){
            e.printStackTrace();
            return -3;
        }
        return epcList.size();
    }

    public int queryLabelContinued(){
        if(!isConn)
            return -1;

        ReaderParameter param = reader.GetInventoryPatameter();
        param.SetSession(0);//设置Session
        param.SetQValue(4);//设置QValue
//				param.SetAntenna(1);//读TID;
        reader.SetInventoryPatameter(param);
        Rfid3Service.MsgCallback callback = new Rfid3Service.MsgCallback();
        reader.SetCallBack(callback);
        int i = reader.StartRead();
        return i;
    }

    public int ColseContinued(){
        if(!isConn)
            return -1;

        reader.StopRead();
        return reader.DisConnect();
    }
    /**
     * 获取epc
     * @return
     */
    public List getEpcs(){
        return epcList;
    }
        /**
         *通过EPC掩码读取各存储区数据
         * @param epcCode
         * @return
         */
    public String readData(String epcCode){
        if(!isConn)
            return "-1";

        if(epcList.indexOf(epcCode) == -1)
            return "-2";

        String rev = reader.ReadDataByEPC(epcCode, (byte)1,(byte)2, (byte)(MAX_LENGTH/2), PASS_WD);
        System.out.println("rev:"+rev);
        return convertHexToString(rev);
    }

    /**
     * 通过EPC掩码向各存储区写数据.最多8个字
     * @param epcCode
     * @param data
     * @return
     */
    public String writeData(String epcCode, String data) {
        if(!isConn)
            return "-1";

        if (epcList.indexOf(epcCode) == -1)
            return "-2";
        String hex = convertStringToHex(data);     //4400是pc控制字，保证能写入16个字节的数据
        int iRev = reader.WriteDataByEPC(epcCode, (byte) 0x01, (byte) 0x01, PASS_WD, "4400" + hex);
        if (iRev == 0) {
            //如果写入成功，需要替换原来寻卡得到的epc
            int pos = epcList.indexOf(epcCode);
            if(pos>-1)
                epcList.set(pos, hex);
            return hex;
        }else
        {
            return String.valueOf(iRev);
        }
    }

    /**
     * 关闭rfid连接
     * @return
     */
    public int disConnect(){
        isConn = false;
        if(reader != null)
            return reader.DisConnect();
        else
            return 0;
    }

    private String convertStringToHex(String str){
        char[] chars = str.toCharArray();
        StringBuffer hex = new StringBuffer();
        int totalLen = chars.length;
        if(totalLen>MAX_LENGTH)
            totalLen = MAX_LENGTH;
        for(int i = 0; i < totalLen; i++){
            hex.append(Integer.toHexString((int)chars[i]));
        }
        if(chars.length<MAX_LENGTH) {                //如果写入的长度小于最大长度，增加asc码0作为结束标志，注意添加标志后总长度要保证是能被4整除（一个字）
            if(chars.length % 2 == 0)
                hex.append("0000");
            else
                hex.append("00");
        }
        return hex.toString();
    }

    private String convertHexToString(String hex){
        StringBuilder sb = new StringBuilder();
        StringBuilder temp = new StringBuilder();
        //49204c6f7665204a617661 split into two characters 49, 20, 4c...
        for( int i=0; i<hex.length()-1; i+=2 ){
            //grab the hex in pairs
            String output = hex.substring(i, (i + 2));
            //convert hex to decimal
            if(output.equals("00"))
                break;
            int decimal = Integer.parseInt(output, 16);
            //convert the decimal to character
            sb.append((char)decimal);
            temp.append(decimal);
        }
        return sb.toString();
    }
}
