/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira.junit
 */
package net.ranides.assira.junit;

import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.IntPredicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public final class LogObserver {
    
    private static final Queue<LogMessage> TARGET = new ConcurrentLinkedQueue<>();
    
    private static final boolean DEBUG = "true".equals(System.getProperty("assira.junit.debug"));
    
    private static final boolean ENABLED = "true".equals(System.getProperty("assira.junit.logger.observe"));
    
    private static volatile boolean debug = DEBUG;
    
    private static volatile boolean enabled = ENABLED;
        
    private LogObserver() {
        /* utility class */
    }
    
    @SuppressWarnings("PMD.SystemPrintln")
    public static void append(int level, String message, Throwable error) {
        if(enabled) {
            TARGET.add(new LogMessage(level, message, error));
        }
        if(debug) {
            System.err.println(message);
            if(null != error) {
                error.printStackTrace(System.err);
            }
        }
    }
    
    public static void debug(boolean value) {
        debug = value;
    }
    
    public static void reset(boolean enabled) {
        TARGET.clear();
        LogObserver.enabled = enabled;
    }
    
    public static List<LogMessage> list() {
        return TARGET.stream().collect(Collectors.toList());
    }
    
    public static Stream<LogMessage> stream() {
        return TARGET.stream();
    }
    
    public static boolean match(Predicate<LogMessage> filter) {
        return stream().anyMatch(filter);
    }
    
    public static Stream<LogMessage> forText(Predicate<String> filter) {
        return stream().filter(m -> filter.test(m.text()));
    }
    
    public static Stream<LogMessage> forText(String text) {
        return stream().filter(m -> text.equals(m.text()));
    }
    
    public static Stream<LogMessage> forLevel(IntPredicate filter) {
        return stream().filter(m -> filter.test(m.level()));
    }
    
    public static Stream<LogMessage> forLevel(int level) {
        return stream().filter(m -> m.level() >= level);
    }
    
}
