package  org.ts.ddcs.Worker;

import com.alibaba.fastjson.JSONObject;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.ts.ddcs.common.constant.GBConstants;
import org.ts.ddcs.dataStream.DataStreamAdapter;
import org.ts.ddcs.kafka.KafkaClient;
import org.ts.ddcs.log.LogHelper;
import org.ts.ddcs.main.DataProcess;
import org.ts.ddcs.main.DataProcessHolder;
import org.ts.ddcs.net.DataChannelHolder;
import org.ts.ddcs.util.BytesUtil;


import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Callable;

/**
 * 下行报文到RTU
 *
 * @author dylan
 */
public class DownloadDatagramTask implements Callable<Integer> {

    private String rtuCode;

    public DownloadDatagramTask(String rtuCode) {
        this.rtuCode = rtuCode;
    }

    @Override
    public Integer call() throws Exception {
        String logId = LogHelper.createLogId("DownloadDatagramTask");
        try {
            LogHelper.info(logId + " 下行报文到 " + rtuCode);
            RedisTemplate redisTemplate = DataProcessHolder.newInstance().dataProcess.redisTemplate;
            HashOperations<String, String, String> opsHash = redisTemplate.opsForHash();
            ListOperations<String, String> opsList = redisTemplate.opsForList();
            if (opsHash.hasKey(rtuCode, "last_connect_id")) {
                String connectId = opsHash.get(rtuCode, "last_connect_id");
                DataStreamAdapter dataStreamAdapter = DataChannelHolder.newInstance().dataChannel.getDataTemplateAdapterByKey(connectId);
                if (null != dataStreamAdapter) {
//                    String master = null;
//
//                    boolean isMaster = false;
//                    if (opsHash.hasKey(rtuCode, GBConstants.REDIS_KEY_SERVER_MASTER)) {
//                        master = opsHash.get(rtuCode, GBConstants.REDIS_KEY_SERVER_MASTER);
//                        if (null != master && master.equals(DataProcess.config().getServerId())) {
//                            isMaster = true;
//                        }
//                    }
                    /**RTU主连接服务器**/
                    // if (isMaster) {
                    LogHelper.info(logId + " " + rtuCode  + " process!");
                    /**升级或下发文件**/
                    if (opsHash.hasKey(rtuCode, GBConstants.REDIS_KEY_COMMAND_FILE)) {
                        String commandJson = opsHash.get(rtuCode, GBConstants.REDIS_KEY_COMMAND_FILE);
                        LogHelper.info(logId + " " + rtuCode + " down file datagram  " + commandJson);
                        JSONObject command = JSONObject.parseObject(commandJson);
                        Date now = new Date();
                        long lastSendTime = command.getLong("lastSendTime");
                        long tryCount = command.getLong("tryCount");
                        String relaydatagram = command.getString(GBConstants.BASE_KEY_DATAGRAM);
                        if (null != relaydatagram) {
                            String outDatagram = "";
                            if (relaydatagram.startsWith("7E7E")) {
                                String p1 = relaydatagram.substring(0, 32);
                                String p2 = BytesUtil.byte2HexStr(BytesUtil.getFBTm());
                                String p3 = relaydatagram.substring(44, relaydatagram.length() - 4);
                                String body = p1 + p2 + p3;
                                byte[] bodyBuff = BytesUtil.hexStr2Bytes(body);
                                byte[] crc16 = BytesUtil.crcFun2014(bodyBuff);
                                bodyBuff = BytesUtil.arrayApend(bodyBuff, crc16);//CRC16
                                outDatagram = BytesUtil.byte2HexStr(bodyBuff);
                            } else {
                                outDatagram = relaydatagram;
                            }
                            dataStreamAdapter.output(BytesUtil.hexStr2Bytes(outDatagram));
                            LogHelper.info(logId + " " + " relay  to " + rtuCode + " " + relaydatagram);
                        }
                        command.put("tryCount", tryCount + 1);
                        command.put("lastSendTime", now.getTime());
                        opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_FILE, command.toJSONString());
                        return 0;
                    }

                    if (redisTemplate.hasKey(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_FILE)) {
                        if (opsList.size(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_FILE) > 0) {
                            if (opsHash.hasKey(rtuCode, GBConstants.REDIS_KEY_COMMAND_FILE)) {
                                opsHash.delete(rtuCode, GBConstants.REDIS_KEY_COMMAND_FILE);
                            }
                            String commandJson = opsList.leftPop(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_FILE);
                            LogHelper.info(logId + " " + rtuCode + " down file datagram  " + commandJson);
                            JSONObject command = JSONObject.parseObject(commandJson);
                            Date now = new Date();
                            String relaydatagram = command.getString(GBConstants.BASE_KEY_DATAGRAM);
                            if (null != relaydatagram) {
                                String outDatagram = "";
                                if (relaydatagram.startsWith("7E7E")) {
                                    String p1 = relaydatagram.substring(0, 32);
                                    String p2 = BytesUtil.byte2HexStr(BytesUtil.getFBTm());
                                    String p3 = relaydatagram.substring(44, relaydatagram.length() - 4);
                                    String body = p1 + p2 + p3;
                                    byte[] bodyBuff = BytesUtil.hexStr2Bytes(body);
                                    byte[] crc16 = BytesUtil.crcFun2014(bodyBuff);
                                    bodyBuff = BytesUtil.arrayApend(bodyBuff, crc16);//CRC16
                                    outDatagram = BytesUtil.byte2HexStr(bodyBuff);
                                } else {
                                    outDatagram = relaydatagram;
                                }
                                dataStreamAdapter.output(BytesUtil.hexStr2Bytes(outDatagram));
                                LogHelper.info(logId + " " + " relay  to " + rtuCode + " " + relaydatagram);
                            }
                            long tryCount = 1;
                            command.put("try", true);
                            command.put("tryCount", tryCount);
                            command.put("lastSendTime", now.getTime());
                            if (command.containsKey("waittingBack")) {
                                boolean waittingBack = command.getBoolean("waittingBack");
                                if (waittingBack) {
                                    opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_FILE, command.toJSONString());
                                }
                            } else {
                                opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_FILE, command.toJSONString());
                            }
                            return 0;
                        }
                    }

                    if (opsHash.hasKey(rtuCode, GBConstants.REDIS_KEY_COMMAND_SETTING)) {
                        String commandJson = opsHash.get(rtuCode, GBConstants.REDIS_KEY_COMMAND_SETTING);
                        LogHelper.info(logId + " " + rtuCode + " down setting datagram  " + commandJson);
                        JSONObject command = JSONObject.parseObject(commandJson);
                        long tryCount = command.getLong("tryCount");
                        if (tryCount < 10) {
                            Date now = new Date();
                            long lastSendTime = command.getLong("lastSendTime");
                            long currTime = now.getTime();
                            String relaydatagram = command.getString(GBConstants.BASE_KEY_DATAGRAM);
                            if (null != relaydatagram) {
                                dataStreamAdapter.output(BytesUtil.hexStr2Bytes(relaydatagram));
                                LogHelper.info(logId + " " + " relay  to " + rtuCode + " " + relaydatagram);
                            }
                            command.put("tryCount", tryCount + 1);
                            command.put("lastSendTime", now.getTime());
                            opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_SETTING, command.toJSONString());
                            return 0;
                        } else {
                            opsHash.delete(rtuCode, GBConstants.REDIS_KEY_COMMAND_SETTING);
                        }
                    }

                    if (redisTemplate.hasKey(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_SETTING)) {
                        if (opsList.size(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_SETTING) > 0) {
                            String commandJson = opsList.leftPop(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_SETTING);
                            LogHelper.info(logId + " " + rtuCode + " down setting datagram  " + commandJson);
                            JSONObject command = JSONObject.parseObject(commandJson);
                            Date now = new Date();
                            String relaydatagram = command.getString(GBConstants.BASE_KEY_DATAGRAM);
                            if (null != relaydatagram) {
                                dataStreamAdapter.output(BytesUtil.hexStr2Bytes(relaydatagram));
                                LogHelper.info(logId + " " + " relay  to " + rtuCode + " " + relaydatagram);
                            }
                            long tryCount = 1;
                            command.put("tryCount", tryCount);
                            command.put("lastSendTime", now.getTime());
                            command.put("try", true);
                            if (command.containsKey("waittingBack")) {
                                boolean waittingBack = command.getBoolean("waittingBack");
                                if (waittingBack) {
                                    opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_SETTING, command.toJSONString());
                                }
                            } else {
                                opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_SETTING, command.toJSONString());
                            }
                            return 0;
                        }
                    }

                    if (opsHash.hasKey(rtuCode, GBConstants.REDIS_KEY_COMMAND_QUERY)) {
                        String commandJson = opsHash.get(rtuCode, GBConstants.REDIS_KEY_COMMAND_QUERY);
                        LogHelper.info(logId + " " + rtuCode + " down query datagram  " + commandJson);
                        JSONObject command = JSONObject.parseObject(commandJson);
                        long tryCount = command.getLong("tryCount");
                        if (tryCount < 10) {
                            Date now = new Date();
                            long lastSendTime = command.getLong("lastSendTime");
                            long currTime = now.getTime();
                            String relaydatagram = command.getString(GBConstants.BASE_KEY_DATAGRAM);
                            if (null != relaydatagram) {
                                dataStreamAdapter.output(BytesUtil.hexStr2Bytes(relaydatagram));
                                LogHelper.info(logId + " " + " relay  to " + rtuCode + " " + relaydatagram);
                            }
                            command.put("tryCount", tryCount + 1);
                            command.put("lastSendTime", now.getTime());
                            opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_QUERY, command.toJSONString());
                        } else {
                            opsHash.delete(rtuCode, GBConstants.REDIS_KEY_COMMAND_QUERY);
                        }
                        return 0;
                    }

                    if (redisTemplate.hasKey(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_QUERY)) {
                        if (opsList.size(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_QUERY) > 0) {
                            String commandJson = opsList.leftPop(rtuCode + ":" + GBConstants.REDIS_KEY_COMMAND_QUERY);
                            LogHelper.info(logId + " " + rtuCode + " down query datagram  " + commandJson);
                            JSONObject command = JSONObject.parseObject(commandJson);
                            Date now = new Date();
                            String relaydatagram = command.getString(GBConstants.BASE_KEY_DATAGRAM);
                            if (null != relaydatagram) {
                                dataStreamAdapter.output(BytesUtil.hexStr2Bytes(relaydatagram));
                                LogHelper.info(logId + " " + " relay  to " + rtuCode + " " + relaydatagram);
                            }
                            long tryCount = 1;
                            command.put("tryCount", tryCount);
                            command.put("lastSendTime", now.getTime());
                            command.put("try", true);
                            if (command.containsKey("waittingBack")) {
                                boolean waittingBack = command.getBoolean("waittingBack");
                                if (waittingBack) {
                                    opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_QUERY, command.toJSONString());
                                }
                            } else {
                                opsHash.put(rtuCode, GBConstants.REDIS_KEY_COMMAND_QUERY, command.toJSONString());
                            }
                            return 0;
                        }
                    }
                    // }
                } else {
                    LogHelper.info(logId + " rtuCode " + rtuCode + " offline");
                    SimpleDateFormat timeFormat = new SimpleDateFormat("yyyyMMddHHmmss");
                    String queue = DataProcess.queueConfig().getServerSelfCheckingMessage();
                    JSONObject body = new JSONObject();
                    body.put("messageKind", "2");
                    JSONObject content = new JSONObject();
                    content.put("time", timeFormat.format(new Date()));
                    content.put("serverName", DataProcessHolder.newInstance().dataProcess.serverName);
                 //   content.put("serverId", DataProcess.config().getServerId());
                    content.put("rtuCode", rtuCode);
                    content.put("rtuStatus", "offline");
                    body.put("message", content.toJSONString());
                    KafkaClient.messageSubmit(queue, body.toJSONString());
                }
            }
        } catch (Exception e) {
            LogHelper.error(e);
        } finally {
            LogHelper.info(logId + " 下行报文下发操作已完成");
        }
        return 0;
    }
}
