package com.imdroid.sideslope.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class WarningServiceImpl implements WarningService {
    @Autowired
    WarningCfgMapper warningCfgMapper;
    @Autowired
    WarningMsgMapper warningMsgMapper;
    @Autowired
    GnssStatusMapper gnssStatusMapper;

    // warning type <-> level & value
    Map<Integer, int[]> cfgMap = new HashMap<>();
    int warningLevel2Code = 0;

    public void refreshCfg(){
        QueryWrapper<WarningCfg> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("devicetype", WarningCfg.TYPE_GNSS);
        List<WarningCfg> cfgList = warningCfgMapper.selectList(null);
        for(WarningCfg cfg: cfgList){
            cfgMap.put(cfg.getType(),new int[]{cfg.getLevel(),cfg.getValue()});
            if(cfg.getLevel() == WarningCfg.LEVEL_2){
                warningLevel2Code |= cfg.getType();
            }
        }
    }
    /***
     * 检查一个周期内的b562数量是否足够
     * @param
     */
    @Override
    public void checkB562Num(String deviceId, Integer tenantId,
                             int[] numB562Stat){
        if(cfgMap.size() == 0) refreshCfg();
        int[] threshold = cfgMap.get(WarningCfg.TYPE_LESS_B562);
        if(threshold != null && (numB562Stat[0] < threshold[1])) {
            // 检测电压和RSSI
            WarningMsg warningMsg = new WarningMsg();
            warningMsg.setDeviceid(deviceId);
            warningMsg.setTenantid(tenantId);
            warningMsg.setCreatetime(LocalDateTime.now());
            warningMsg.setDevicetype(WarningCfg.TYPE_GNSS);
            warningMsg.setCode(WarningCfg.TYPE_LESS_B562);
            warningMsg.setLevel((short) threshold[0]);
            warningMsg.setInfo(WarningCfg.TYPE_NAME_LESS_B562+"，固定解:" + numB562Stat[0] + "，非固定解:"+numB562Stat[1]+"，无B562:"+numB562Stat[2]);
            warningMsgMapper.insert(warningMsg);
        }

        GnssStatus status = gnssStatusMapper.getByDeviceId(deviceId);
        if(0 == numB562Stat[0]){
            // 记录连续无固定解的轮数
            if(status != null){
                int count = status.getNoreslutcount()+1;
                status.setNoreslutcount(count);
                int[] threshold2 = cfgMap.get(WarningCfg.TYPE_NO_FIXED_RESULT);
                if(count >= threshold2[1]){
                    // 连续6个周期无固定解则产生严重告警
                    WarningMsg warningMsg = new WarningMsg();
                    warningMsg.setDeviceid(deviceId);
                    warningMsg.setTenantid(tenantId);
                    warningMsg.setCreatetime(LocalDateTime.now());
                    warningMsg.setDevicetype(WarningCfg.TYPE_GNSS);
                    warningMsg.setCode(WarningCfg.TYPE_NO_FIXED_RESULT);
                    warningMsg.setLevel((short) threshold2[0]);
                    warningMsg.setInfo("连续" + count+"周期无固定解");
                    warningMsgMapper.insert(warningMsg);
                    status.setWarningcode(status.getWarningcode()|WarningCfg.TYPE_NO_FIXED_RESULT);
                    // 根据告警码确定告警级别
                    status.setWarning(getWarningLevel(status.getWarningcode()));
                }
                gnssStatusMapper.updateById(status);
            }
        }
        else{
            if((status.getWarningcode()&WarningCfg.TYPE_NO_FIXED_RESULT) != 0){
                status.setWarningcode(status.getWarningcode() & ~WarningCfg.TYPE_NO_FIXED_RESULT);
                status.setWarning(getWarningLevel(status.getWarningcode()));
                status.setNoreslutcount(0);
                gnssStatusMapper.updateById(status);
            }
        }
    }
    /***
     * 检查电压、RSSI等
     * @param statusMsg
     */
    @Override
    public void checkDeviceStatus(GnssStatusMsg statusMsg, GnssStatus curStatus){
        if(cfgMap.size() == 0) refreshCfg();
        // 清除离线告警
        if(curStatus.getWarningcode() == null) curStatus.setWarningcode(0);
        curStatus.setWarningcode(curStatus.getWarningcode() & ~WarningCfg.TYPE_DEVICE_OFF_LINE);

        // 检测电压和RSSI
        WarningMsg warningMsg = new WarningMsg();
        warningMsg.setDeviceid(statusMsg.getDeviceid());
        warningMsg.setTenantid(statusMsg.getTenantid());
        warningMsg.setCreatetime(LocalDateTime.now());
        warningMsg.setDevicetype(WarningCfg.TYPE_GNSS);

        int[] lowVoltage = cfgMap.get(WarningCfg.TYPE_LOW_VOLTAGE);
        if(lowVoltage!=null){
            if(statusMsg.getVoltage() <= lowVoltage[1]) {
                warningMsg.setCode(WarningCfg.TYPE_LOW_VOLTAGE);
                warningMsg.setLevel((short) lowVoltage[0]);
                warningMsg.setInfo("低电压：" + statusMsg.getVoltage() + "mV");
                warningMsgMapper.insert(warningMsg);
                //告警级别
                curStatus.setWarningcode(curStatus.getWarningcode() | WarningCfg.TYPE_LOW_VOLTAGE);
            }
            else{
                //清除告警
                curStatus.setWarningcode(curStatus.getWarningcode() & ~WarningCfg.TYPE_LOW_VOLTAGE);
            }
        }

        int[] lowRSSI = cfgMap.get(WarningCfg.TYPE_LOW_RSSI);
        if(lowRSSI!=null){
            if(statusMsg.getRssi() <= lowRSSI[1]) {
                warningMsg.setCode( WarningCfg.TYPE_LOW_RSSI);
                warningMsg.setLevel((short) lowRSSI[0]);
                warningMsg.setInfo("4G信号弱：" + statusMsg.getRssi());
                warningMsgMapper.insert(warningMsg);
                //告警级别
                curStatus.setWarningcode(curStatus.getWarningcode() | WarningCfg.TYPE_LOW_RSSI);
            }
            else{
                //清除告警
                curStatus.setWarningcode(curStatus.getWarningcode() & ~WarningCfg.TYPE_LOW_RSSI);
            }
        }

        // 根据告警码确定告警级别
        curStatus.setWarning(getWarningLevel(curStatus.getWarningcode()));

    }
    /***
     * 检查未知报文是否较多
     * @param msg
     */
    @Override
    public void checkTrx(GnssTrxMsg msg, GnssStatus curStatus){

    }

    public short getWarningLevel(int warningCode){
        if(warningCode == 0) return WarningCfg.LEVEL_0;
        else if((warningCode & warningLevel2Code) !=0 ) return WarningCfg.LEVEL_2;
        else return WarningCfg.LEVEL_1;
    }
}
