package ru.yandex.webmaster3.storage.spamban;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ru.yandex.webmaster3.storage.user.SpamBanRule;
import ru.yandex.webmaster3.storage.user.dao.SpamBanCountersRedisService;
import ru.yandex.wmtools.common.data.info.IPInfo;

/**
 * Created by ifilippov5 on 25.01.17.
 */
@Service
public class SpamBanManager {
    private static final Logger log = LoggerFactory.getLogger(SpamBanManager.class);

    private ExecutorService executor;
    private BlockingQueue<Ip> ips = new ArrayBlockingQueue<>(100);

    @Autowired
    private SpamBanCountersRedisService spamBanCountersRedisService;

    public void init() {
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setDaemon(true)
                .setNameFormat("ipHandler-%d")
                .build();
        executor = Executors.newSingleThreadExecutor(threadFactory);
        executor.execute(() -> {
            while (true) {
                Ip ip;
                try {
                    ip = ips.take();
                    if (Thread.interrupted()) {
                        log.warn("Interrupted");
                        break;
                    }
                    if (ip == null)
                        continue;
                } catch (InterruptedException e) {
                    log.warn("Interrupted");
                    break;
                }
                ip.increment();
            }
        });
    }

    public void destroy() {
        executor.shutdownNow();
        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            // Ignore
        }
    }

    public void handle(SpamBanRule rule) {
        ips.offer(() -> spamBanCountersRedisService.increment(rule.getRuleId()));
    }

    public void handle(IPInfo ip) {
        ips.offer(() -> spamBanCountersRedisService.increment(ip.getAddressAsString()));
    }

    public interface Ip {
        void increment();
    }
}
