package com.brilliance.isc.warn.impl;

import com.brilliance.mda.runtime.mda.IStream;
import com.brilliance.mda.runtime.mda.impl.StreamImpl;
import com.brilliance.mda.runtime.mda.util.Systems;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import com.brilliance.isc.utils.StringUtils;
import com.brilliance.isc.vo.WarnVo;
import com.brilliance.isc.warn.WarnService;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class WarnServiceImpl implements WarnService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static ThreadLocal<List<WarnVo>> warningListLocal = new ThreadLocal<List<WarnVo>>() {
        @Override
        protected List<WarnVo> initialValue() {
            return new ArrayList<>();
        }
    };

    /**
     * 设置重要警告
     *
     * @param id
     * @param message
     */
    @Override
    public void importantWarn(String id, String message) {
        buildWarns(WarnVo.LEVEL_IMPORTANT, id, "", "", message,new Object[0]);
    }

    @Override
    public void importantWarn(String id, String subId, String source, String message) {
        buildWarns(WarnVo.LEVEL_IMPORTANT, id, subId, source, message,new Object[0]);
    }

    @Override
    public void importantWarn(String id, String subId, String source, String message, Object[] val) {
        buildWarns(WarnVo.LEVEL_IMPORTANT, id, subId, source, message,val);
    }

    /**
     * 设置一般警告
     *
     * @param id
     * @param message
     */
    @Override
    public void generalWarn(String id, String message) {
        buildWarns(WarnVo.LEVEL_GENERAL, id, "", "", message,new Object[0]);
    }

    @Override
    public void generalWarn(String id, String subId, String source, String message) {
        buildWarns(WarnVo.LEVEL_GENERAL, id, subId, source, message,new Object[0]);
    }

    @Override
    public void generalWarn(String id, String subId, String source, String message, Object[] val) {
        buildWarns(WarnVo.LEVEL_GENERAL, id, subId, source, message,val);
    }

    /**
     * 设置提示警告
     *
     * @param id
     * @param message
     */
    @Override
    public void tipWarn(String id, String message) {
        buildWarns(WarnVo.LEVEL_TIPS, id, "", "", message,new Object[0]);
    }

    @Override
    public void tipWarn(String id, String subId, String source, String message) {
        buildWarns(WarnVo.LEVEL_TIPS, id, subId, source, message,new Object[0]);
    }

    @Override
    public void tipWarn(String id, String subId, String source, String message, Object[] val) {
        buildWarns(WarnVo.LEVEL_TIPS, id, subId, source, message,val);
    }

    /**
     * 返回所有的警告信息
     *
     * @return
     */
    @Override
    public List<WarnVo> getAndClearTotalWarns() {
        List<WarnVo> warnVoList = warningListLocal.get();
        clearWarn();
        return warnVoList;
    }

    /**
     * 返回所有的警告信息
     *
     * @return
     */
    @Override
    public List<WarnVo> getTotalWarns() {
        List<WarnVo> warnVoList = warningListLocal.get();
        return warnVoList;
    }

    /**
     * 警告消息插入 删除 更新操作
     *
     * @param level
     * @param id
     * @param subId
     * @param source
     * @param message
     */
    private void buildWarns(String level, String id, String subId, String source, String message) {
        buildWarns(level,id,subId,source,message,new Object[0]);
    }

    private void buildWarns(String level, String id, String subId, String source, String message,Object[] val) {
        String key = id + "_" + subId + "_" + source;
        List<WarnVo> warnVoList = warningListLocal.get();
        //1.如果消息为空 通过key删除原来的警告信息
        if (StringUtils.isEmpty(message)) {
            Iterator<WarnVo> iterator = warnVoList.iterator();
            while (iterator.hasNext()) {
                WarnVo warnVo = iterator.next();
                if (key.equals(warnVo.getKey())) {
                    iterator.remove();
                }
            }
        } else {
            //2.判断是否能找到 找到需要更新消息以及消息级别
            WarnVo findWarnVo = null;
            for (WarnVo warnVo : warnVoList) {
                if (key.equals(warnVo.getKey())) {
                    findWarnVo = warnVo;
                    break;
                }
            }
            if (findWarnVo != null) {
                findWarnVo.setMessage(message);
                findWarnVo.setLevel(level);
                findWarnVo.setVal(val);
            } else {
                //3.没有找到  直接插入
                findWarnVo = new WarnVo();
                findWarnVo.setId(id);
                findWarnVo.setSubId(subId);
                findWarnVo.setSource(source);
                findWarnVo.setLevel(level);
                findWarnVo.setMessage(message);
                findWarnVo.setReadFlag("N");
                findWarnVo.setVal(val);
                warnVoList.add(findWarnVo);
            }
        }
    }

    /**
     * 清除所有的警告信息，执行前后掉一下
     */
    @Override
    public void clearWarn() {
        warningListLocal.remove();
    }

    public static List<WarnVo> directGetAndClearTotalWarns() {
        List<WarnVo> warnVoList = warningListLocal.get();
        warningListLocal.remove();
        return warnVoList;
    }

    /**
     * 放置警告信息列表，多用于SPT TAKE、快照回显
     */
    @Override
    public void putWarnList(List<WarnVo> warnList) {
        List<WarnVo> warnVoList = warningListLocal.get();
        if (warnList != null) {
            warnVoList.addAll(warnList);
        }
    }

    /**
     * 检查warning消息是否平衡
     * <p>
     * * @param oldWarningList
     *
     * @return
     */
    @Override
    public boolean checkWarningBalance(List<WarnVo> oldWarningList) {
        List<WarnVo> backWarningList = null;
        if (oldWarningList != null) {
            backWarningList = oldWarningList
                    .stream().filter(warnVo -> WarnVo.SOURCE_BACK.equals(warnVo.getSource()))
                    .collect(Collectors.toList());
        }
        String oldWarningMac = calcMac(backWarningList);
        List<WarnVo> warningList = warningListLocal.get()
                .stream().filter(warnVo -> WarnVo.SOURCE_BACK.equals(warnVo.getSource()))
                .collect(Collectors.toList());
        String warningMac = calcMac(warningList);
        if (!oldWarningMac.equals(warningMac)) {
            logger.info("Warning Mac:{}, New Warning Mac:{},2次mac值不一样，检核不通过，需要返回前端", oldWarningMac, warningMac);
            return false;
        }
        return true;
    }

    @Override
    public void buildwarning(String level, String id, String subId, String source, String message) {
        buildwarning(level,id,subId,source,message,new Object[0]);
    }

    @Override
    public void buildwarning(String level, String id, String subId, String source, String message, Object[] val) {
        String key = id + "_" + subId + "_" + source;
        List<WarnVo> warnVoList = warningListLocal.get();
        //1.如果消息为空 通过key删除原来的警告信息
        WarnVo findWarnVo = null;
        if (StringUtils.isEmpty(message)) {
            Boolean contains = false;
            Iterator<WarnVo> iterator = warnVoList.iterator();
            while (iterator.hasNext()) {
                WarnVo warnVo = iterator.next();
                if (key.equals(warnVo.getKey())) {
                    contains = true;
                    warnVo.setMessage("");
                }
            }
            if (!contains) {
                findWarnVo = new WarnVo();
                findWarnVo.setId(id);
                findWarnVo.setSubId(subId);
                findWarnVo.setSource(source);
                findWarnVo.setLevel(level);
                findWarnVo.setMessage(message);
                findWarnVo.setReadFlag("N");
                findWarnVo.setVal(val);
            }
        } else {
            //2.判断是否能找到 找到需要更新消息以及消息级别
            for (WarnVo warnVo : warnVoList) {
                if (key.equals(warnVo.getKey())) {
                    findWarnVo = warnVo;
                    break;
                }
            }
            if (findWarnVo != null) {
                findWarnVo.setMessage(message);
                findWarnVo.setLevel(level);
                findWarnVo.setVal(val);
            } else {
                //3.没有找到  直接插入
                findWarnVo = new WarnVo();
                findWarnVo.setId(id);
                findWarnVo.setSubId(subId);
                findWarnVo.setSource(source);
                findWarnVo.setLevel(level);
                findWarnVo.setMessage(message);
                findWarnVo.setReadFlag("N");
                findWarnVo.setVal(val);
            }
        }
        if (findWarnVo != null) {
            warnVoList.add(findWarnVo);
        }
    }

    /**
     * 计算警告信息的mac值
     *
     * @param warnList
     * @return
     */
    private String calcMac(List<WarnVo> warnList) {
        if (warnList == null || warnList.size() == 0) {
            return "";
        }
        //1，2进行计算mac
        IStream stream = new StreamImpl();
        for (WarnVo warnVo : warnList) {
            if("3".equals(warnVo.getLevel()) || "4".equals(warnVo.getLevel())){
                continue;
            }
            stream.addLine(warnVo.toString());
        }
        if (stream.isEmpty()) {
            return "";
        }
        return Systems.macGen(stream, 0);
    }
}
