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

import com.alibaba.fastjson.JSONObject;
import io.netty.util.internal.StringUtil;
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.PaintshopArea;
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 net.vtstar.zhongtong.avi.monitoring.service.StationPassInfoService;
import net.vtstar.zhongtong.avi.utils.EquipDataUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.core.annotation.Order;
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
@Order(value = 99)
//@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;
    @Resource(name = "webStationCache")
    private Cache webStationCache;

    @Autowired
    private StationPassInfoService passInfoService;
    @Autowired
    private ModbusTemplate modbusTemplate;
    @Autowired
    private PaintshopStationMapper stationMapper;
    @Autowired
    private StationPassInfoMapper passInfoMapper;
    @Resource(name = "redisTemplate")
    protected ValueOperations testValueOperations;

    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");
        if (null == id){
            id = json.getString("TID");
        }
        Integer state = json.getIntValue("State");
        if (StringUtil.isNullOrEmpty(id)) {
            return;
        }

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

        if (id.startsWith("A61A")) {
            log.error("过滤掉乱发信息！：{},平移车:{}", id, vehicleCode);
            return;
        }

        Skid skid = (Skid) valueOperations.get(Constant.SKID_PREFIX + id);
        //若是焊装车间进车，绑定滑撬与车身关系
        if (state == 1 && (vehicleCode.equals(Constant.HANZHUANG_VEHICLE1_RFID) || vehicleCode.equals(Constant.HANZHUANG_VEHICLE2_RFID))) {
            //记录焊装上车的信息
            listOperations.rightPush("rfid:log:" + vehicleCode, messageBO);

            String busNo = (String) valueOperations.get(Constant.HANZHUANG_VEHICLE_BUSNO_KEY + vehicleCode);
            String workOrderNo = (String) valueOperations.get(Constant.HANZHUANG_VEHICLE_WORKNO_KEY + vehicleCode);
            if (null == busNo) {
                log.error("未录入PDA车身号！ ：" + vehicleCode);
                return;
            }
            if (null == skid) {
                skid = new Skid();
                skid.setRfid(id);
                skid.setBusNo(busNo);
                skid.setWorkOrderNo(workOrderNo);
                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 = 1;
            }else {
                size ++;
            }
            valueOperations.set(key, size);
            String keyW = EquipDataUtil.getTestValueKey(Constant.ROTARY_ROLLER_BED_C);
            testValueOperations.set(keyW, null == testValueOperations.get(keyW) ? 0 : ((int)testValueOperations.get(keyW)) + 1);
            return;
        }
        //todo: 因PDA未使用, 暂不做此逻辑判断
        /*if (null == skid) {
            log.error("无滑撬信息！ ：" + vehicleCode);
            return;
        }*/

        Vehicle vehicle = (Vehicle) valueOperations.get(Constant.VEHICLE_PREFIX + vehicleCode);
        if (null == vehicle) {
            vehicle = vehicleCache.get(vehicleCode, Vehicle.class);
        }

        String rfid = vehicle.getCurrentRfid();
        //若当前平移车上绑定了RFID, 并且与当前mqtt信息中的ID一致, 并且state=1, 则认为这是读写头的重发现象
        if (null != rfid && id.equals(rfid)) {
            if (state == 1) {
                Date occurTime = vehicle.getOccurTime();
                if (null != occurTime) {
                    long l = (date.getTime() - occurTime.getTime()) / 1000;
                    if (l < 30) {
//                        log.error("{} 平移车发生重发现象 ,滑撬id {}", vehicleCode, id);
                        vehicle.setOccurTime(date);
                        valueOperations.set(Constant.VEHICLE_PREFIX + vehicleCode, vehicle);
                        return;
                    }
                }
            }
        }
        //平移车过车信息
        listOperations.rightPush("rfid:log:" + vehicleCode, messageBO);

        if (state == 0) {
            vehicle.setState(false);
            if (null != skid){
                vehicle.setSkid(skid);
            }
            vehicle.setOccurTime(new Date());
            valueOperations.set(Constant.VEHICLE_PREFIX + vehicleCode, vehicle);
            return;
        }
        //TODO: 若上车时, 发现此滑撬号未被绑定过, 则有两种情况: 漏读/系统启动前就上线的
        if (null == skid){
            skid = new Skid();
            skid.setRfid(id);
            skid.setBusNo("");
            skid.setWorkOrderNo("TZ0010051107_0011");
            skid.setBusType(ProductionType.OWN);
            valueOperations.set(Constant.SKID_PREFIX + id, skid);
        }
        vehicle.setState(true);
        vehicle.setOccurTime(date);
        vehicle.setCurrentRfid(id);
        vehicle.setSkid(skid);
        //   valueOperations.set(Constant.VEHICLE_PREFIX + vehicleCode, vehicle);


        List<PaintshopArea> areas = webStationCache.get("stationList", ArrayList.class);
        if (null == areas){
            return;
        }
        for (PaintshopArea area : areas) {
            Map<String, PaintshopStation> stationMap = area.getStationMap();
            if (null == stationMap){
                continue;
            }
            for (Map.Entry<String, PaintshopStation> entry : stationMap.entrySet()) {
                PaintshopStation value = entry.getValue();
                //因目前无法保证上撬工位一定位于平移车道两侧, 所以不再判断车道信息
                /*if (!vehicle.getLane().equals(value.getVehicleLaneCode())) {
                    continue;
                }*/

                if (StationState.FREE.equals(value.getState())) {
                    continue;
                }
                //TODO: 因当前环境中存在未上线的滑撬, 所以skid有可能为空
                if(null == value.getSkid()){
                    continue;
                }
                if (id.equals(value.getSkid().getRfid())) {
                    List<PaintshopStation> lands = new ArrayList<>();
                    List<PaintshopStation> temStation = laneStationCache.get(value.getLaneId(), ArrayList.class);
                    for (PaintshopStation land : temStation) {
                        PaintshopStation s = (PaintshopStation) valueOperations.get(Constant.STATION_PREFIX + land.getCode());
                        lands.add(s);
                    }

                    lands.sort(Comparator.comparing(v -> v.getSequence()));

                    PaintshopStation start = lands.get(0);
                    PaintshopStation end = lands.get(lands.size() - 1);
                    if (start.getCode().equals(value.getCode())) {

                        if(null == start.getSkid()){
                            start.setSkid(value.getSkid());
                        }
                        vehicle.setSkid(start.getSkid());
                        vehicle.setCurrentRfid(start.getSkid().getRfid());

                        for (int j = 1; j <= lands.size() - 2; j++) {
                            PaintshopStation tem = lands.get(j);
                            PaintshopStation tem2 = lands.get(j - 1);
                            if (tem.getSkid() != null) {
                                tem2.setSkid(tem.getSkid());
                                tem2.setState(StationState.USE);
                            } else {
                                tem2.setState(StationState.FREE);
                                tem2.setSkid(null);
                            }
                            tem.setState(StationState.FREE);
                            tem.setSkid(null);
                        }
                        if (null != start.getPassInfoId()){
                            passInfoService.endPassInfo(start);
                        }
                    } else if (end.getCode().equals(value.getCode())) {
                        if(null == end.getSkid()){
                            end.setSkid(value.getSkid());
                        }
                        vehicle.setSkid(end.getSkid());
                        vehicle.setCurrentRfid(end.getSkid().getRfid());

                        for (int j = lands.size() - 2; j >= 0; j--) {
                            PaintshopStation tem = lands.get(j);
                            PaintshopStation tem2 = lands.get(j + 1);
                            if (tem.getSkid() != null) {
                                tem2.setState(StationState.USE);
                                tem2.setSkid(tem.getSkid());
                            } else {
                                tem2.setState(StationState.FREE);
                                tem2.setSkid(null);
                            }
                            tem.setState(StationState.FREE);
                            tem.setSkid(null);
                        }
                        if (null != end.getPassInfoId()){
                            passInfoService.endPassInfo(end);
                        }
                    }else{
                        //因现场错误干扰, 导致滑撬不在两端工位
                        for (PaintshopStation land : lands) {
                            if (land.getSkid() != null && id.equals(land.getSkid().getRfid())){
                                land.setSkid(null);
                                land.setState(StationState.FREE);
                                if (null != land.getPassInfoId()){
                                    passInfoService.endPassInfo(land);
                                }
                            }
                        }
                    }

                    //TODO: 记录过站信息
                    String areaCode = value.getAreaId().toString();
                    String areaKey = Constant.BUS_SIZE_OUT + areaCode + ":" + today;
                    Integer size = (Integer) valueOperations.get(areaKey);
                    if (null == size) {
                        size = 1;
                    } else {
                        size++;
                    }
                    valueOperations.set(areaKey, size);

                    for (PaintshopStation land : lands) {
                        valueOperations.set(Constant.STATION_PREFIX + land.getCode(), land);
                    }
                    valueOperations.set(Constant.VEHICLE_PREFIX + vehicleCode, vehicle);
                    return;
                }
            }
        }
        valueOperations.set(Constant.VEHICLE_PREFIX + vehicleCode, vehicle);
        //若为涂装首工位上车, 且为焊装刚刚过来的, 此时无法从工位列表中找到滑撬信息, 所以单独处理
        if (vehicleCode.equals(Constant.TUZHUANG_VEHICLE1_RFID)){
            valueOperations.set(Constant.VEHICLE_PREFIX + vehicleCode, vehicle);
            String keyW = EquipDataUtil.getTestValueKey(Constant.ROTARY_ROLLER_BED_P1);
            testValueOperations.set(keyW, null == testValueOperations.get(keyW) ? 0 : ((int)testValueOperations.get(keyW)) + 1);
        }
        if (vehicleCode.equals("rfid67")){
            String keyW = EquipDataUtil.getTestValueKey(Constant.ROTARY_ROLLER_BED_P2);
            testValueOperations.set(keyW, null == testValueOperations.get(keyW) ? 0 : ((int)testValueOperations.get(keyW)) + 1);
            String areaKey = Constant.BUS_SIZE_OUT + "1" + ":" + today;
            Integer size = (Integer) valueOperations.get(areaKey);
            if (null == size) {
                size = 1;
            } else {
                size++;
            }
            valueOperations.set(areaKey, size);
        }

//        // 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)) {
//
//            }
//        }

    }
}
