package org.ts.ddcs.Worker;

import com.alibaba.fastjson.JSONObject;
import org.ts.ddcs.DataItemTemplate.DataItemTemplateInterface;
import org.ts.ddcs.Entity.RelayDatagramRecordEntity;
import org.ts.ddcs.Log.LogHelper;
import org.ts.ddcs.Service.RtuService;
import org.ts.ddcs.Tool.BytesHelp;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.Callable;

@SuppressWarnings("all")
public class DataGramXAMSzy2012RelayProcess implements Callable<Integer> {

    private String _rtuCode;
    private String _ip;
    private String _datagram;
    private Date _collectTime;
    private Date _pickTime;
    private HashMap<String, DataItemTemplateInterface> dataItem;

    DataGramXAMSzy2012RelayProcess(String rtuCode, Date collectTime, Date pickTime, String ip, String datagram) {
        this._rtuCode = rtuCode;
        this._collectTime = collectTime;
        this._pickTime = pickTime;
        this._ip = ip;
        this._datagram = datagram;
    }



    @Override
    public Integer call() {
        RelayDatagramRecordEntity relayRecord = new RelayDatagramRecordEntity();
        try {
            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            SimpleDateFormat timeFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            relayRecord.setDatagram(this._datagram);
            relayRecord.setRtuCode(this._rtuCode);
            relayRecord.setRelayIp(this._ip);
            relayRecord.setCollectTime(timeFormat2.format(this._collectTime));
            relayRecord.setPickTime(timeFormat2.format(this._pickTime));

            Socket socket = null;
            OutputStream outputStream = null;
            InputStream inputStream = null;
            LogHelper.info("DataGramSzy2012RelayProcess " + this._rtuCode + " " + this._ip + " " + this._datagram);
            String[] ips = this._ip.split(":");
            if (null == ips || ips.length != 2) {
                LogHelper.info("DataGramSzy2012RelayProcess ip error " + this._rtuCode + " " + this._ip);
                relayRecord.setRelayError("ip error ");
                return 0;
            }
            String host = ips[0];
            int port = Integer.parseInt(ips[1]);
            socket = new Socket(host, port);
            outputStream = socket.getOutputStream();

            String  repackageDatagram="";

            String afn = this._datagram.substring("682468B31522001A00".length(),"682468B31522001A00C0".length());
            if (afn.equals("C0")){
                //重新生成RTU编码，后两个字节互换
                String  xamRtuCode= this._datagram.substring("682468B3".length(),"682468B3152200".length());
                xamRtuCode += this._datagram.substring("682468B31522001A".length(),"682468B31522001A00".length());
                xamRtuCode += this._datagram.substring("682468B3152200".length(),"682468B31522001A".length());


                String dataContent ="";
                dataContent += this._datagram.substring("682468".length(),"682468B3".length());//控制域
                dataContent += xamRtuCode;//地址域
                dataContent += "C0";
                dataContent += this._datagram.substring("682468B31522001A00C0".length(),"682468B31522001A00C0".length()+20);//瞬时、累计
                dataContent += "0000000000";//小时累计
                dataContent += "FFFFFFFFFF";
                dataContent += this._datagram.substring(this._datagram.length()-"0000700000001410008A16".length(),this._datagram.length());//状态，时间


                byte[] crcstrbuff = BytesHelp.hexStr2Bytes(dataContent);
                byte[] crc = new byte[1]; //系统计算的校验码
                crc[0] = BytesHelp.GetCRCByte(crcstrbuff);


                byte[] lenbuff = new byte[1];
                lenbuff[0] = (byte) crcstrbuff.length;

                repackageDatagram = "68" + BytesHelp.byte2HexStr(lenbuff) + "68" + dataContent + BytesHelp.byte2HexStr(crc) + "16";
            }else{
                repackageDatagram = this._datagram;
            }
            LogHelper.info(this._rtuCode + " repackage  datagram" + repackageDatagram);
            byte[] sendBuff = BytesHelp.hexStr2Bytes(repackageDatagram);
            relayRecord.setDatagramProcess(repackageDatagram);

            //发送报文数据
            outputStream.write(sendBuff);
            //记录报文发送时间
            relayRecord.setRelayTime(timeFormat2.format(new Date()));
            Thread.sleep(500);
            inputStream = socket.getInputStream();

            if (sendBuff[10] == (byte) 0x2f) {
                LogHelper.info("DataGramSzy2012RelayProcess  链路报 无回报 " + this._rtuCode);
                relayRecord.setRelayResult("0");
                relayRecord.setBackTime(timeFormat.format(new Date()));
            } else {

                byte[] buff = new byte[1024];
                int len = 0;
                byte[] bytes = new byte[1];
                int count = 0;
                int timeout = 0;
                int packlen = 0;
                int step = 0;
                while (true) {
                    int read = inputStream.available();
                    if (read <= 0) {
                        if (timeout > 10000) {
                            break;
                        }
                        Thread.sleep(500);
                        timeout += 500;
                    } else {
                        len = inputStream.read(bytes, 0, 1);
                        if (len != -1) {
                            if (len > 0) {
                                System.arraycopy(bytes, 0, buff, count, len);
                                count += len;
                                if (step == 0) {

                                    if (count == 3) {
                                        if (buff[0] == (byte) 0x68 && buff[2] == (byte) 0x68) {

                                            packlen = 5 + (int) buff[1];
                                            step = 1;
                                        } else {
                                            buff[0] = buff[1];
                                            buff[1] = buff[2];
                                            count -= 1;
                                        }
                                    }

                                } else {

                                    if (count == packlen) {
                                        break;
                                    }
                                }
                            }

                        } else {
                            break;
                        }
                    }
                }

                if (count > 0 && count == packlen) {
                    /**收到回报*/
                    relayRecord.setBackTime(timeFormat2.format(new Date()));
                    relayRecord.setDatagramBack(BytesHelp.byte2HexStr(buff, 0, count));

                    LogHelper.info("relay datagram back " + this._rtuCode + " " + relayRecord.getDatagramBack());
                    if (packlen > 5) {
                        byte[] crc = new byte[1];
                        crc[0] = BytesHelp.GetCRCByte(BytesHelp.subBytes(buff, 3, packlen - 5));
                        byte[] baowenCrc = BytesHelp.subBytes(buff, packlen - 2, 1);

                        if (crc[0] != baowenCrc[0]) {
                            relayRecord.setRelayResult("1");
                            LogHelper.info("DataGramSzy2012RelayProcess 校验失败 " + this._rtuCode + " CHECK CRC=" + BytesHelp.byte2HexStr(crc) + "-PACKET CRC=" + BytesHelp.byte2HexStr(baowenCrc));
                        } else {
                            relayRecord.setRelayResult("0");
                            LogHelper.info("DataGramSzy2012RelayProcess 校验成功 " + this._rtuCode + " CHECK CRC=" + BytesHelp.byte2HexStr(crc) + "-PACKET CRC=" + BytesHelp.byte2HexStr(baowenCrc));
                        }
                    }
                } else {
                    LogHelper.info("relay datagram dont get back " + this._rtuCode);
                    relayRecord.setRelayError("relay datagram dont get back");
                }

            }

            Thread.sleep(5000);
            outputStream.close();
            inputStream.close();
            socket.close();
        } catch (Exception e) {

            LogHelper.info("relay datagram error " + this._rtuCode);
            relayRecord.setRelayResult("1");
            relayRecord.setRelayError("relay datagram system error happen!");
            LogHelper.error(e);
        } finally {
            //记录转发信息
            String jsonStr = JSONObject.toJSONString(relayRecord);
            LogHelper.info("relay datagram record " + jsonStr);
            RtuService rtuService = DataProcessHolder.newInstance().dataProcess.rtuService;
            rtuService.SaveRelayDatagramInfo(relayRecord);
        }
        return 0;
    }
}
