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 DataGramSw2014RelayProcess implements Callable<Integer> {

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

    DataGramSw2014RelayProcess(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("yyyy-MM-dd HH:mm:ss");
            relayRecord.setDatagram(this._datagram);
            relayRecord.setRtuCode(this._rtuCode );
            relayRecord.setRelayIp(this._ip);
            relayRecord.setCollectTime(timeFormat.format(this._collectTime));
            relayRecord.setPickTime(timeFormat.format(this._pickTime));

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

            relayRecord.setRelayTime(timeFormat.format(new Date()));

            Thread.sleep(500);
            inputStream = socket.getInputStream();
            if (sendBuff[10] == (byte) 0x2f) {
                LogHelper.info("DataGramSw2014RelayProcess  链路报 无回报 "+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 == 13) {
                                        if (buff[0] == (byte) 0x7e && buff[1] == (byte) 0x7e) {


                                            byte[] dataAreaLen = new byte[2];
                                            dataAreaLen[0] = buff[11];
                                            dataAreaLen[1] = buff[12];
                                            String dflag = BytesHelp.byte2HexStr(dataAreaLen);
                                            dflag = "0" + dflag.substring(1, dflag.length());
                                            byte[] lenbuff = BytesHelp.hexStr2Bytes(dflag);
                                            int contensize = BytesHelp.bytes2Int(lenbuff, 0, 2);// 报文长度(int)

                                            packlen = 17 + contensize;

                                            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(timeFormat.format(new Date()));
                    relayRecord.setDatagramBack( BytesHelp.byte2HexStr(buff, 0, count));
                    LogHelper.info("relay datagram back " + this._rtuCode +" "+relayRecord.getDatagramBack());
                    byte[] PacketCrc16 = new byte[2];
                    PacketCrc16[0] = buff[packlen - 2];
                    PacketCrc16[1] = buff[packlen - 1];
                    //生成校验码,包体，去掉报文最后两个字节
                    byte[] crc16 = BytesHelp.crcFun2014(BytesHelp.subBytes(buff, 0, packlen - 2));
                    if (!BytesHelp.byte2HexStr(PacketCrc16).equals(BytesHelp.byte2HexStr(crc16))) {
                        LogHelper.info("校验码错误：报文中 CRC=" + BytesHelp.byte2HexStr(PacketCrc16) + " 计算的 CRC=" + BytesHelp.byte2HexStr(crc16));
                        relayRecord.setRelayResult("1");
                    } else {
                        LogHelper.info("校验码成功：报文中 CRC=" + BytesHelp.byte2HexStr(PacketCrc16) + " 计算的 CRC=" + BytesHelp.byte2HexStr(crc16));
                        relayRecord.setRelayResult("0");
                    }
                } 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.setRelayError("relay datagram system error happen!");
            relayRecord.setRelayResult("1");
            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;
    }
}
