/**
 * Copyright (c) 2010-2012 EBM WebSourcing, 2012-2015 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see <http://www.gnu.org/licenses/>
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.log.handler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

/**
 * @author aruffie Class with represent a test memory handler aspect. It provide
 *         several methods to interact with a ordered <List> which store
 *         <LogRecord> in memory.
 */
public final class TestHandler extends Handler {

    // The buffer
    private final List<LogRecord> records;

    public TestHandler() {
        records = new ArrayList<LogRecord>();
    }

    /**
     * Allow to return all logged records.
     * 
     * @return <List<LogRecord>>
     */
    public List<LogRecord> getAllRecords() {
        return Collections.unmodifiableList(this.records);
    }

    /**
     * Allow to return all logged records for a specific provided <Level>.
     * 
     * @param level
     *            The <Level> of seeked records.
     * @return <List<LogRecord>>
     */
    public List<LogRecord> getAllRecords(final Level level) {

        final List<LogRecord> records = new ArrayList<LogRecord>();

        for (final LogRecord logRecord : this.records) {
            if (logRecord.getLevel().equals(level)) {
                records.add(logRecord);
            }
        }

        return records;
    }

    /**
     * Allow to clear the buffer.
     */
    public void clearRecords() {
        this.records.clear();
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.util.logging.Handler#publish(java.util.logging.LogRecord)
     */
    public void publish(final LogRecord record) {
        if (!isLoggable(record)) {
            return;
        }
        /*
         * Put the new entry in <List> in order to keep this entry in memory
         */
        this.records.add(record);
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.util.logging.Handler#flush()
     */
    public void flush() {
        // Nothing to do for this implementation
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.util.logging.Handler#close()
     */
    public void close() throws SecurityException {
        // Nothing to do for this implementation
    }

    /**
     * Return a <TestHandler> if the provided <Logger> in parameter has one,
     * else return null.
     * 
     * @param logger
     *            The specified <Logger>
     * @return Return an implementation of <TestHandler>
     */
    public static TestHandler extractTestHandler(final Logger logger) {
        final Handler[] handlers = logger.getHandlers();

        if (handlers != null && handlers.length > 0) {
            for (final Handler handler : handlers) {

                /*
                 * If handler is a TestHandler implementation return it.
                 */
                if (handler.getClass().isAssignableFrom(TestHandler.class)) {
                    return (TestHandler) handler;
                }
            }
        }

        return null;
    }
    
    /**
     * Get a logger with the specified logger name and only the test handler 
     * (all the previous handlers are removed)
     * 
     * @param loggerName a logger name
     * @param testHandler a test handler
     * @return a logger with the specified logger name and test handler
     */
    public static final Logger getLoggerWithTestHandler(String loggerName, TestHandler testHandler) {
        assert loggerName != null;
        assert testHandler != null;
        
        final Logger logger = Logger.getLogger(loggerName);
        for (Handler h : logger.getHandlers())
            logger.removeHandler(h);
        logger.addHandler(testHandler);
        return logger;
    }
}
