package net.vtstar.zhongtong.avi.mqtt.handle;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.vtstar.protocol.modbus.tcp.netty.service.ModbusTemplate;
import net.vtstar.scada.base.global.service.ModbusService;
import net.vtstar.scada.base.mqtt.utils.MqttConstants;
import net.vtstar.user.mybatis.provider.Operation;
import net.vtstar.user.mybatis.provider.OrderBy;
import net.vtstar.user.mybatis.provider.WhereFilter;
import net.vtstar.zhongtong.avi.equipment.domain.PaintshopStation;
import net.vtstar.zhongtong.avi.equipment.domain.RuntimeRecord;
import net.vtstar.zhongtong.avi.equipment.mapper.PaintshopStationMapper;
import net.vtstar.zhongtong.avi.global.constant.Constant;
import net.vtstar.zhongtong.avi.monitoring.domain.Skid;
import net.vtstar.zhongtong.avi.monitoring.domain.StationPassInfo;
import net.vtstar.zhongtong.avi.monitoring.domain.Vehicle;
import net.vtstar.zhongtong.avi.monitoring.domain.bo.MQTTMessageBO;
import net.vtstar.zhongtong.avi.monitoring.domain.enums.ProductionType;
import net.vtstar.zhongtong.avi.monitoring.domain.enums.StationState;
import net.vtstar.zhongtong.avi.monitoring.mapper.StationPassInfoMapper;
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.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class RfidMessageHandler extends AbstractTesterMessageHandler {

    public static MQTTMessageBO messageBO = new MQTTMessageBO();
    public static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy:MM:dd");


    @Autowired
    private RedisTemplate redisTemplate;

    @Resource(name = "redisTemplate")
    private ListOperations listOperations;

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

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

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

    @Autowired
    private ModbusService modbusService;
    @Autowired
    private ModbusTemplate modbusTemplate;
    @Autowired
    private PaintshopStationMapper stationMapper;
    @Autowired
    private StationPassInfoMapper passInfoMapper;

    public RfidMessageHandler() {
        super("translation", "data/all");
    }

    @Override
    public void handleMessage(Message<?> message) throws MessagingException {

        Date date = new Date();
        Object payload = message.getPayload();
        JSONObject json = JSONObject.parseObject(payload.toString());

        String id = json.getString("ID");
        Integer state = json.getIntValue("State");

        String today = dateFormat.format(date);
        //存rfid log日志
        messageBO.setID(id);
        messageBO.setState(state);
        String currentDate = format.format(date);
        messageBO.setCreateDate(currentDate);
        MessageHeaders headers = message.getHeaders();
        String vehicleCode = headers.get(MqttConstants.MSG_HEADER_KEY_EQUIPMENTNUMBER, String.class);

        log.info(vehicleCode + "______" + json.toJSONString() + " code：" + vehicleCode);
        listOperations.rightPush("rfid:log:" + vehicleCode, messageBO);
        Map<String, Vehicle> vehicleMap = hashOperations.entries("vehicle");

        if (id.equals("A61A0000000000000000000000000")) {
            log.error("读写头错误！");
            return;
        }
        Skid skid = (Skid) valueOperations.get(Constant.SKID_PREFIX + id);
        if (state == 1 && (vehicleCode.equals(Constant.HANZHUANG_VEHICLE1_RFID) || vehicleCode.equals(Constant.HANZHUANG_VEHICLE1_RFID))) {
            String busNo = (String) valueOperations.get(Constant.HANZHUANG_VEHICLE1_BUSNO_KEY + vehicleCode);
            if (null == busNo) {
                log.error("未录入PDA车身号！ ：" + vehicleCode);
                return;
            }
            if (null == skid) {
                skid = new Skid();
                skid.setRfid(id);
                skid.setBusNo(busNo);
                skid.setBusType(ProductionType.OWN);
                valueOperations.set(Constant.SKID_PREFIX + id, skid);
            }
            String format = dateFormat.format(date);
            String key = Constant.BUS_SIZE_IN + "0:" + format;
            Integer size = (Integer) valueOperations.get(key);
            if (null == size) {
                size = 0;
            }
            valueOperations.set(key, size);
            return;
        }
        if (null == skid) {
            log.error("无滑撬信息！ ：" + vehicleCode);
            return;
        }
        Vehicle vehicle = vehicleMap.get(vehicleCode);
        if (null == vehicle) {
            vehicle = vehicleCache.get(vehicleCode, Vehicle.class);
        }
        // TODO: 2019-11-02 获得正反转信息，以及相邻的工位
        Integer land = vehicle.getLane();
        //Set<String> keys = redisTemplate.keys(Constant.STATION_PREFIX + land + ":*");

        List<PaintshopStation> arriveList = new ArrayList<>();

        List<PaintshopStation> stationList = laneStationCache.get(land.toString(), ArrayList.class);
        for (PaintshopStation station : stationList) {
            String code = station.getCode();
            PaintshopStation sta = (PaintshopStation) valueOperations.get(Constant.STATION_PREFIX + code);
            if (null == sta) {
                sta = stationCache.get(code, PaintshopStation.class);
            }
            if (null == sta.getArrive()) {
                continue;
            }
            if (sta.getArrive()) {
                arriveList.add(sta);
            }
        }
        if (CollectionUtils.isEmpty(arriveList)) {
            log.error("找不到对平移车到位信号！ 平移车 id：{},滑撬 {}", vehicle.getCode(), id);
            return;
        }

        List<PaintshopStation> collect = arriveList.stream().filter(sta -> (sta.getTurnF() != null && sta.getTurnR() != null)).collect(Collectors.toList());
        Map<String, List<PaintshopStation>> listMap = collect.stream().collect(Collectors.groupingBy(PaintshopStation::getLandNo));

        PaintshopStation sourceStation = new PaintshopStation();
        if (CollectionUtils.isEmpty(listMap)) {
            return;
        }
        if (listMap.size() > 1) {
            Set<String> veKeys = redisTemplate.keys(Constant.VEHICLE_PREFIX);
            if (CollectionUtils.isEmpty(veKeys) || veKeys.size() != listMap.size()) {
                log.error("平移车读写信号数量：{} 与 到位信号数量不一致！{}", veKeys.size(), listMap.size());
                return;
            }
            for (String veKey : veKeys) {
                Vehicle v = (Vehicle) valueOperations.get(veKey);
            }
        } else {
            List<PaintshopStation> stations = listMap.get(0);
            if (stations.size() == 1) {
                sourceStation = stations.get(0);
            } else {
                PaintshopStation sta = stations.get(0);
                // if (state == 1 && (sta.getTurnR() && )){
            }
        }
        Long laneId = sourceStation.getLaneId();

        vehicle.setCurrentRfid(id);
        StationState oldState = null;
        String oldSkidId = null;
        if (state == 1) {
            //获得正反转信息,得到平移车相邻工位信息
            List<PaintshopStation> stations;
            stations = stationMapper.findList(new WhereFilter() {{
                addFilter(PaintshopStation.class, "lane_id", Operation.EQUAL, laneId);
                addOrderBy(RuntimeRecord.class, "sequence", OrderBy.DESC);
            }}, PaintshopStation.class);

            for (PaintshopStation station : stations) {
                station.setOldState(oldState);
                station.setSkidID(oldSkidId);
                oldState = station.getState();
                oldSkidId = station.getSkidID();
                station.setState(StationState.USE);
                station.setSkidID(id);
            }
            String currentRfid = vehicle.getCurrentRfid();
            vehicle.setCurrentRfid(null);

            //记录过站数及信息
            savePassInfo(today, currentDate, skid, sourceStation);
        } else if (state == 0) {
            List<PaintshopStation> stations = new ArrayList<>();
            for (PaintshopStation station : stations) {
                station.setOldState(oldState);
                station.setSkidID(oldSkidId);
                oldState = station.getState();
                oldSkidId = station.getSkidID();
                station.setState(StationState.FREE);
                station.setSkidID(id);
            }
            PaintshopStation station = new PaintshopStation();
            station.setState(StationState.FREE);
            station.setSkidID(null);

            //记录过站数及信息
            String areaCode = sourceStation.getAreaId().toString();
            String key = Constant.BUS_SIZE_IN + areaCode + ":" + today;
            Integer size = (Integer) valueOperations.get(key);
            if (null == size) {
                size = 0;
            } else {
                size++;
            }
            valueOperations.set(key, size);

            List<StationPassInfo> list = passInfoMapper.findList(new WhereFilter() {{
                addFilter("area_no", Operation.EQUAL, areaCode);
                addFilter("out_time", Operation.IS, "null");
            }}, StationPassInfo.class);
            if (CollectionUtils.isEmpty(list)){

            }
        }

    }

    private void savePassInfo(String today, String currentDate, Skid skid, PaintshopStation sourceStation) {
        String key = Constant.BUS_SIZE_OUT + sourceStation.getAreaId().toString() + ":" + today;
        Integer size = (Integer) valueOperations.get(key);
        if (null == size) {
            size = 0;
        } else {
            size++;
        }
        valueOperations.set(key, size);
        StationPassInfo info = new StationPassInfo();
        info.setAreaNo(sourceStation.getAreaId().toString());
        info.setRfid(skid.getRfid());
        info.setVIN(skid.getBusNo());
        info.setIn_time(currentDate);
        info.setStationNo(sourceStation.getCode());
        passInfoMapper.insert(info);
    }
}
