package com.srbenoit.log;

import java.util.logging.Filter;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;
import java.util.logging.StreamHandler;

/**
 * A handler to direct output to <code>System.out</code>. The source code for this class is copied
 * from the Java SDK source code for <code>ConsoleHandler</code>, with the exception that it writes
 * to <code>System.out</code> rather than <code>System.err</code>.
 */
public final class SysOutConsoleHandler extends StreamHandler {

    /**
     * Configures the handler.
     */
    private void configure() {

        LogManager manager;
        String cname;
        String val;
        Class<?> clz;

        manager = LogManager.getLogManager();
        cname = getClass().getName();

        val = manager.getProperty(cname + ".level");

        if (val == null) {
            setLevel(Level.INFO);
        } else {
            setLevel(Level.parse(val.trim()));
        }

        val = manager.getProperty(cname + ".filter");

        if (val == null) {
            setFilter(null);
        } else {

            try {
                clz = ClassLoader.getSystemClassLoader().loadClass(val);
                setFilter((Filter) clz.newInstance());
            } catch (Exception e) {
                setFilter(null);
            }
        }

        val = manager.getProperty(cname + ".formatter");

        if (val != null) {

            try {
                clz = ClassLoader.getSystemClassLoader().loadClass(val);
                setFormatter((Formatter) clz.newInstance());
            } catch (Exception ex1) {
                publish(new LogRecord(Level.SEVERE, "Failed to load formatter class"));
            }
        }

        try {
            val = manager.getProperty(cname + ".encoding");

            if (val == null) {
                setEncoding(null);
            } else {
                setEncoding(val.trim());
            }
        } catch (Exception ex1) {

            try {
                setEncoding(null);
            } catch (Exception ex2) {
                publish(new LogRecord(Level.SEVERE, "Failed to set handler encoding"));
            }
        }
    }

    /**
     * Constructs a new <code>SysOutConsoleHandler</code>.
     */
    public SysOutConsoleHandler() {

        super(System.out, new SimpleFormatter());

        configure();
    }

    /**
     * Publishes a <code>LogRecord</code>.
     *
     * <p>The logging request was made initially to a <code>Logger</code> object, which initialized
     * the <code>LogRecord</code> and forwarded it here.
     *
     * <p>
     *
     * @param  record  description of the log event (a <code>null</code> record is silently ignored
     *                 and is not published)
     */
    @Override public synchronized void publish(final LogRecord record) { // NOPMD

        super.publish(record);
        flush();
    }

    /**
     * Overrides <code>StreamHandler.close</code> to do a flush but not to close the output stream.
     * That is, we do <b>not</b> close <code>System.out</code>.
     */
    @Override public synchronized void close() { // NOPMD

        flush();
    }
}
