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

import lombok.extern.slf4j.Slf4j;
import net.vtstar.protocol.modbus.tcp.netty.packet.ReadCoilsResponse;
import net.vtstar.protocol.modbus.tcp.netty.packet.ReadMultipleRegistersResponse;
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.user.mybatis.provider.Operation;
import net.vtstar.user.mybatis.provider.WhereFilter;
import net.vtstar.zhongtong.avi.equipment.domain.PaintshopStation;
import net.vtstar.zhongtong.avi.equipment.mapper.PaintshopStationMapper;
import net.vtstar.zhongtong.avi.monitoring.domain.Vehicle;
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.stereotype.Component;
import org.springframework.util.CollectionUtils;

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

@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;

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

        List<EquipInfo> equipInfoList = equipInfoService.getEquipInfoList(EQUIPMENT_TYPE);
        if (CollectionUtils.isEmpty(equipInfoList)) {
            return;
        }
        equipInfoList.forEach(equipInfo -> {
            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) {

                    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;
                    if (1 == startTemplate.getFunctionCode()) {
                        try {
                            ReadCoilsResponse response = modbusService.readCoilRegister(slaveId, poolKey, startAddress, count);
                            Map<String, PaintshopStation> stationMap = stationCache.get("station", HashMap.class);
                            for (EquipDataTemplateItem item : itemList) {
                                String fieldName = item.getFieldName();
                                if (fieldName.startsWith("stationState")) {
                                    String stationCode = fieldName.split("_")[1];
                                    PaintshopStation station = stationCache.get(stationCode, PaintshopStation.class);
                                    byte state = response.getBody().readByte();
                                    station.setOldState(station.getState());
                                    station.setState(state == 0 ? StationState.FREE : StationState.USE);
                                    stationMap.put(stationCode, station);
                                }
                                if (fieldName.startsWith("vehicle_signal")) {
                                    String[] split = fieldName.split("_");
                                    String vehicleCode = split[3];
                                    Map<String, Vehicle> map = hashOperations.entries("vehicle_signal");
                                    Vehicle vehicle = map.get(vehicleCode);
                                    byte state = response.getBody().readByte();
                                    if (split[2].equals("left")) {
                                        vehicle.setLeftSignal(state == 0 ? true : false);
                                    }
                                    if (split[2].equals("right")) {
                                        vehicle.setRightSignal(state == 0 ? true : false);
                                    }
                                }
                            }
                            stationCache.put("station", stationMap);
                        } catch (Exception e) {
                            log.info("读取失败。ip{}，端口{},slave{},start{}", poolKey.getHost(), poolKey.getPort(), slaveId, startAddress);
                        }
                    }
                    if (3 == startTemplate.getFunctionCode()) {
                        try {
                            ReadMultipleRegistersResponse response = modbusService.readMultipleRegister(slaveId, poolKey, startAddress, count);
                        } catch (Exception e) {
                            log.info("读取失败。ip{}，端口{},slave{},start{}", poolKey.getHost(), poolKey.getPort(), slaveId, startAddress);
                        }
                    }
                }
            }
        });

    }


    public Object handleValue(String fieldName, Object value) {
        if (fieldName.startsWith("stationState")) {
            String stationCode = fieldName.split("_")[1];
            List<PaintshopStation> stationList = stationMapper.findList(new WhereFilter() {{
                addFilter("code", Operation.EQUAL, stationCode);
            }}, PaintshopStation.class);
            if (CollectionUtils.isEmpty(stationList)) {
                throw new IllegalArgumentException("找不到编号为：" + stationCode + "：的工位！");
            }
            PaintshopStation station = stationList.get(0);
            Integer state = (Integer) value;
            station.setState(state == 0 ? StationState.FREE : StationState.USE);
        }
        //if (fieldName.startsWith())
        return value;
    }
}
