package net.vtstar.zhongtong.avi.monitoring.job;

import lombok.extern.slf4j.Slf4j;
import net.vtstar.protocol.modbus.tcp.netty.packet.AbstractModbusResponse;
import net.vtstar.protocol.modbus.tcp.netty.utils.NettyUtils;
import net.vtstar.protocol.modbus.tcp.netty.utils.PoolKey;
import net.vtstar.scada.base.equipmgt.domain.*;
import net.vtstar.scada.base.equipmgt.service.EquipInfoService;
import net.vtstar.scada.base.gather.job.GatherJob;
import net.vtstar.scada.base.global.service.ModbusService;
import net.vtstar.zhongtong.avi.equipment.domain.PaintshopStation;
import net.vtstar.zhongtong.avi.equipment.mapper.PaintshopStationMapper;
import net.vtstar.zhongtong.avi.global.constant.Constant;
import net.vtstar.zhongtong.avi.monitoring.domain.enums.StationState;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;

@Slf4j
@Component
public class AVIMonitorJob extends GatherJob {

    private static final String EQUIPMENT_TYPE = "PLC";

    @Autowired
    private EquipInfoService equipInfoService;
    @Autowired
    private PaintshopStationMapper stationMapper;
    @Autowired
    private ModbusService modbusService;

    @Resource(name = "stationCache")
    private Cache stationCache;

    @Resource(name = "redisTemplate")
    protected HashOperations hashOperations;

    @Resource(name = "redisTemplate")
    private ValueOperations valueOperations;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {

        List<EquipInfo> equipInfoList = equipInfoService.getEquipInfoList(EQUIPMENT_TYPE);
        if (CollectionUtils.isEmpty(equipInfoList)) {
            return;
        }
//        Map<String, PaintshopStation> stationMap = hashOperations.entries("station");
//        Map<String, Vehicle> vehicleMap = hashOperations.entries("vehicle_signal");

        long l = System.currentTimeMillis();
        int total = 0;
        int error = 0;
        int timeout = 0;
        int errorTotal = 0;

        for (EquipInfo equipInfo : equipInfoList) {

            List<EquipCommunication> commList = equipInfoService.getCommunicationList(equipInfo.getEquipCode(), 1);
            if (CollectionUtils.isEmpty(commList)) {
                return;
            }
            for (EquipCommunication communication : commList) {
                EquipDataChannel dataChannel = communication.getDataChannel();
                String ip = dataChannel.getIp();
                Integer port = dataChannel.getPort();
                PoolKey poolKey = NettyUtils.wrapPoolKey(ip, port);
                Integer slaveId = dataChannel.getNo();
                EquipDataTemplate template = communication.getDataTemplate();
                if (template == null) {
                    log.info("无法获取设备的数据模板，设备编号：{}", dataChannel.getEquipCode());
                    continue;
                }
                List<EquipDataTemplateItem> templateItemList = template.getTemplateItemList();
                if (CollectionUtils.isEmpty(templateItemList)) {
                    log.info("无法获取数据模板的条目，设备编号：{},模板名称：{}", dataChannel.getEquipCode(), template.getName());
                    continue;
                }
                List<List<EquipDataTemplateItem>> lists = modbusService.groupByAddress(templateItemList);
                for (List<EquipDataTemplateItem> itemList : lists) {

                    Constant.totalSize ++;
                    total = total + 1;

                    EquipDataTemplateItem startTemplate = itemList.get(0);
                    Integer startAddress = startTemplate.getAddress();
                    Integer endAddress = itemList.get(itemList.size() - 1).getAddress();
                    Integer quantity = itemList.get(itemList.size() - 1).getLength();
                    Integer count = endAddress + quantity - startAddress;
                    AbstractModbusResponse response = null;

                    long start = System.currentTimeMillis();

                    try {
                        if (1 == startTemplate.getFunctionCode()) {
                            response = modbusService.readCoilRegister(slaveId, poolKey, startAddress, count);
                        } else if (2 == startTemplate.getFunctionCode()) {
                            response = modbusService.readInputDiscretes(slaveId, poolKey, startAddress, count);
                        } else if (3 == startTemplate.getFunctionCode()) {
                            response = modbusService.readMultipleRegister(slaveId, poolKey, startAddress, count);
                        } else if (4 == startTemplate.getFunctionCode()) {
                            response = modbusService.readInputRegister(slaveId, poolKey, startAddress, count);
                        }
                    } catch (Exception e) {
                        log.error("读取失败。ip{}， 端口{}, slave{}, start{}", poolKey.getHost(), poolKey.getPort(), slaveId, startAddress);
                        continue;
                    }
                    long end = System.currentTimeMillis();
                    log.debug("readTime：" + (end - start));
                    log.debug("___");
                    log.debug("slaveID：" + slaveId + "  start：" + startAddress + " count：" + count + " functionCode：" + startTemplate.getFunctionCode());
                    if (null == response) {
                        log.error("读取异常！");
                        error++;
                        log.error("异常次数！：" + error);
                        continue;
                    }
                    if (!response.isSuccess()) {
                        errorTotal++;
                        String error1 = response.getError();
                        if (error1.contains("秒内与对端连接")) {
                            Constant.totalTimeOut ++ ;
                            timeout++;
                            log.error("超时次数！：" + timeout);
                        }
                        log.error(error1);
                        continue;
                    }

                    for (EquipDataTemplateItem item : itemList) {
                        String fieldName = item.getFieldName();
                        if (fieldName.startsWith("station:ve")) {
                            String stationCode = fieldName.split(":")[2];
                            PaintshopStation station = (PaintshopStation) valueOperations.get(Constant.STATION_PREFIX + stationCode);
                            log.debug("__________________");
                            log.debug("stationCode " + stationCode);
                            if (null == station) {
                                station = stationCache.get(stationCode, PaintshopStation.class);
                            }

                            byte state = response.getBody().readByte();
                            if ((state & 0x01) == 0) {
                                state = 0;
                            } else {
                                state = 1;
                            }
                            log.debug(station.toString());
                            station.setOldState(station.getState());
                            station.setArrive(state == 1 ? true : false);
                            valueOperations.set(Constant.STATION_PREFIX + stationCode, station);
                        }
                        if (fieldName.startsWith("station:turn")) {
                            String[] split = fieldName.split(":");
                            String stationCode = fieldName.split(":")[2];

                            PaintshopStation station = (PaintshopStation) valueOperations.get(Constant.STATION_PREFIX + stationCode);
                            if (null == station) {
                                station = stationCache.get(stationCode, PaintshopStation.class);
                            }
                            byte state = response.getBody().readByte();
                            if ((state & 0x01) == 0) {
                                state = 0;
                            } else {
                                state = 1;
                            }
                            station.setOldState(station.getState());
                            String turn = split[1];
                            if (turn.endsWith("F")) {
                                station.setTurnF(state == 1 ? true : false);
                            }
                            if (turn.endsWith("R")) {
                                station.setTurnR(state == 1 ? true : false);
                            }
                            valueOperations.set(Constant.STATION_PREFIX + stationCode, station);
                        }
                    }
                }
            }
        }
        ;
        log.debug("_________________________________________________");
        log.debug("_________________________________________________");
        log.debug("total" + total);
        log.debug("error" + error);
        log.debug("timeout" + timeout);
        long l1 = System.currentTimeMillis();
        log.debug("time：" + (l1 - l) / 1000) ;

        log.error("Constant size" + Constant.totalSize);
        log.error("Constant timeout" +  Constant.totalTimeOut);
    }

}
