package com.apobates.forum.trident.controller.helper;

import java.time.LocalDateTime;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import com.apobates.forum.member.entity.MemberOnline;
import com.apobates.forum.utils.cache.DelayedUpdateMap;
import com.apobates.forum.utils.cache.DelayedUpdateMapElement;

/**
 * 在线记录时间缓冲剂
 * 
 * @author xiaofanku
 * @since 20200608
 */
public final class MemberOnlineCreationCache {
    private final DelayedUpdateMap updateMap;
    private final Function<MemberOnline,DelayedUpdateMapElement> mapping = (MemberOnline mo)->{
        return new DelayedUpdateMapElement(){
            @Override
            public String getUnionKey() {
                return mo.getMid()+"";
            }
            @Override
            public LocalDateTime getActiveDateTime() {
                return mo.getActiveDateTime();
            }
        };
    };
    
    private MemberOnlineCreationCache(final int cacheUnit){
        this.updateMap = new DelayedUpdateMap(cacheUnit);
    }
    
    private static class LazySingleton{
        private static final MemberOnlineCreationCache INS=new MemberOnlineCreationCache(3);//3分钟
    }
    
    /**
     * 获得3分钟间隔的缓存实例
     * @return 
     */
    public static MemberOnlineCreationCache getSingleton(){
        return LazySingleton.INS;
    }
    
    /**
     * 更新缓存
     * 
     * @param memberOnline 会员在线记录
     * @return 返回值表示缓存更新是否成功,true更新成功
     */
    public boolean put(final MemberOnline memberOnline){
        Objects.requireNonNull(memberOnline);
        return updateMap.put(mapping.apply(memberOnline));
    }
    
    /**
     * 更新缓存
     * 供测试使用
     * @param memberOnline 会员在线记录
     * @param action 缓存更新成功后的消费动作
     */
    public void put(final MemberOnline memberOnline, Consumer<LocalDateTime> action){
        if(put(memberOnline)){
            action.accept(memberOnline.getActiveDateTime());
        }
    }
    
    /**
     * 消费缓存中的SessionKey和更近的活跃日期
     * 供测试使用
     * @param action 消费动作
     */
    public void each(BiConsumer<String, LocalDateTime> action){
        updateMap.each(action);
    }
}
