package com.apobates.forum.utils.cache;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 使用ConcurrentLinkedDeque来实现缓存集合
 * @param <T>
 * @author xiaofanku
 * @since 20200726
 */
public final class CubbyHoleLinkedDeque<T> extends AbstractCubbyHole<T>{
    private final ConcurrentLinkedDeque<T> queue;
    private final static Logger logger = LoggerFactory.getLogger(CubbyHoleLinkedDeque.class);
    
    public CubbyHoleLinkedDeque(final CubbyHoleProcessor<T> processor) {
        super();
        this.queue = new ConcurrentLinkedDeque<>();
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) { //判断是否被中断
                List<T> rs = new ArrayList<>();
                for (T obj = queue.poll(); obj != null; obj = queue.poll()) {
                    rs.add(obj);
                }
                removeAll(rs, processor);
                try{
                    Thread.currentThread().sleep(1000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
    }
    
    @Override
    public boolean put(final T value) {
        //往里放
        return queue.add(value);
    }
    
    @Override
    public void putAll(final Collection<T> values) {
        //往里放
        queue.addAll(values);
    }
    
    public void each(final Consumer<T> action) {
        queue.forEach(action);
    }
    
    private void remove(final T data, final CubbyHoleProcessor<T> processor) {
        if(null == data){
            return;
        }
        removeAll(Arrays.asList(data), processor);
    }
    
    private void removeAll(final Collection<T> data, final CubbyHoleProcessor<T> processor) {
        if(null == data || data.isEmpty()){
            return;
        }
        final Set<String> affect = processor.process(data);
        boolean bol=queue.removeIf(aed -> affect.contains(CubbyHoleLinkedDeque.toChecksum(aed)));
        logger.info("[CH][Dequre]Clear Keys: "+String.join(",", affect)+", result: "+bol);
    }
}
