package com.zd.laboratory.event;

import cn.hutool.core.util.StrUtil;
import com.zd.common.core.constant.CacheConstants;
import com.zd.common.core.enums.HardwareOperate;
import com.zd.common.core.enums.SenseStateEnum;
import com.zd.common.core.utils.SpringUtils;
import com.zd.laboratory.event.handle.EventHandler;
import com.zd.laboratory.mqtt.entiy.EquipmentStatus;
import com.zd.laboratory.mqtt.entiy.SensorStatus;
import com.zd.laboratory.service.ILabAbnormalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 当前由于没有消息中间件，所以只能暂时采用此种方式直接消费数据
 * 而且由于服务端空间问题，高哥没让建新的项目
 * 所以现在存在的问题：
 * 1，发布订阅模式无法解决消息竞争的问题，当前通过服务去监听redis key 变动，实际是基于发布订阅模式，导致微服务存在状态，
 * 当实例启动越多，会对消息处理存在重复处理的情况，应用的水平扩展存在问题，目前该类中消息处理的内容还是幂等的，问题不是很大
 * 解决方法
 * 1，将监听还有socket 等独立出来作为单体应用，剔除对服务状态有影响的部分，（缺点，该部分变成了单节点） 通过消息中间件 异步发送消息，
 * 采用生产者消费者模式消费数据
 *
 *
 *
 * @Author: zhoupan
 * @Date: 2021/10/20/11:19
 * @Description:
 */
@Component
public class RedisExpiredAndAddListener implements MessageListener {

    //监听的主题  现在只监听0号数据库
    private  final PatternTopic topic = new PatternTopic("__keyevent@0__:expired");



    private Map<String,EventHandler> map ;

    public RedisExpiredAndAddListener(List<EventHandler> eventHandlers)
    {
        map = eventHandlers.stream().collect(Collectors.toMap(a -> a.handleKey(), Function.identity()));
    }

    @Override
    public void onMessage(Message message, byte[] bytes) {
//        String topic = new String(bytes);
        String expiredKey = new String(message.getBody());
        String s = StrUtil.subBefore(expiredKey, ":", false);
        Optional.ofNullable(s)
                .map(a -> StrUtil.isNotBlank(s))
                .map(a -> map.get(s+":"))
                .ifPresent(a->a.handle(expiredKey));
    }


    public PatternTopic getTopic() {
        return topic;
    }
}
