package org.wcs.business.stacker;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.wcs.business.data.intf.IDataRecorder;
import org.wcs.constant.enums.business.SseEventTypeEnum;
import org.wcs.helper.SseHelper;
import org.wcs.model.bo.stacker.StackerStatusData;
import org.wcs.model.po.app.AppStackerInfo;
import org.wcs.plugin.plc.model.StackerStatus;
import org.wcs.utils.AppStringUtils;
import org.wcs.utils.AppThreadUtils;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 堆垛机状态监控
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class StackerStatusMonitor {

    private final IDataRecorder dataRecorder; // 数据记录器
    private final SseHelper sseHelper;

    @Getter
    private Map<Integer, StackerStatusData> stackerStatusDataMap;

    /**
     * 设置堆垛机状态
     * @param stackerInfo 堆垛机信息
     * @param status 堆垛机状态
     */
    public void setStackerStatus(AppStackerInfo stackerInfo, StackerStatus status) {
        if(stackerStatusDataMap == null) {
            stackerStatusDataMap = new ConcurrentHashMap<>();
        }
        StackerStatusData stackerStatusData = stackerStatusDataMap.get(stackerInfo.getStackerId());
        // 还没有存在这个堆垛机的信息
        if(stackerStatusData == null) {
            StackerStatusData stackerStatusDataItem = new StackerStatusData();
            stackerStatusDataItem.setStackerId(stackerInfo.getStackerId());
            stackerStatusDataItem.setStackerName(stackerInfo.getStackerName());
            stackerStatusDataItem.setUpdateTime(LocalDateTime.now());
            stackerStatusDataItem.setStatus(status);
            stackerStatusDataMap.put(stackerInfo.getStackerId(), stackerStatusDataItem);
            if(status.getErrCode() != 0) {
                newStackerError(stackerInfo, Integer.valueOf(status.getErrCode()));
            }
            return;
        }
        // 已经存在这个堆垛机的信息
        // ---- 检测是否报警
        if(!Objects.equals(stackerStatusData.getStatus().getErrCode(), status.getErrCode()) && status.getErrCode() != 0) {
            newStackerError(stackerInfo, Integer.valueOf(status.getErrCode()));
        }
        // 插入新信息
        stackerStatusData.setStackerId(stackerInfo.getStackerId());
        stackerStatusData.setStackerName(stackerInfo.getStackerName());
        stackerStatusData.setUpdateTime(LocalDateTime.now());
        stackerStatusData.setStatus(status);
        stackerStatusDataMap.put(stackerInfo.getStackerId(), stackerStatusData);
    }

    /**
     * 堆垛机报警
     * @param stackerInfo 堆垛机信息
     * @param errorCode 报警码
     */
    private void newStackerError(AppStackerInfo stackerInfo, Integer errorCode) {
        AppThreadUtils.startNewThread(() -> {
            log.info("堆垛机{}报警，报警码：{}", stackerInfo.getStackerName(), errorCode);
            dataRecorder.recordStackerErr(stackerInfo.getStackerName(), String.valueOf(stackerInfo.getStackerId()), errorCode);
            sseHelper.SendEventToAll(SseEventTypeEnum.SYSTEM_INFO, String.format("%s 发生报警：%d", stackerInfo.getStackerName(), errorCode));
        });
    }



}
