package com.hammurapi.common.concurrent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.LogRecord;

/**
 * Dispatches logging to several loggers.
 * @author Pavel Vlasov
 *
 */
public class CompositeLogger implements Logger {
	
	private Logger[] loggers;

	public CompositeLogger(Logger... loggers) {
		this.loggers = loggers;
	}

	public CompositeLogger(Iterator<Logger> lit) {
		Collection<Logger> accumulator = new ArrayList<Logger>();
		while (lit.hasNext()) {
			accumulator.add(lit.next());
		}
		loggers = accumulator.toArray(new Logger[accumulator.size()]);
	}

	@Override
	public void fine(String msg) {
		for (Logger logger: loggers) {
			logger.fine(msg);
		}
	}

	@Override
	public void finer(String msg) {
		for (Logger logger: loggers) {
			logger.finer(msg);
		}
	}

	@Override
	public void finest(String msg) {
		for (Logger logger: loggers) {
			logger.finest(msg);
		}
	}

	@Override
	public void info(String msg) {
		for (Logger logger: loggers) {
			logger.info(msg);
		}
	}

	@Override
	public void severe(String msg) {
		for (Logger logger: loggers) {
			logger.severe(msg);
		}
	}

	@Override
	public void warning(String msg) {
		for (Logger logger: loggers) {
			logger.warning(msg);
		}
	}

	@Override
	public void log(Level level, String msg) {
		for (Logger logger: loggers) {
			logger.log(level, msg);
		}
	}

	@Override
	public void log(Level level, String msg, Object param1) {
		for (Logger logger: loggers) {
			logger.log(level, msg, param1);
		}
	}

	@Override
	public void log(Level level, String msg, Object[] params) {
		for (Logger logger: loggers) {
			logger.log(level, msg, params);
		}
	}

	@Override
	public void log(Level level, String msg, Throwable thrown) {
		for (Logger logger: loggers) {
			logger.log(level, msg, thrown);
		}
	}

	@Override
	public void log(LogRecord record) {
		for (Logger logger: loggers) {
			logger.log(record);
		}
	}

	private Map<String, Logger> subLoggers = new ConcurrentHashMap<String, Logger>();

	@Override
	public Logger getLogger(String name) {
		Logger ret = subLoggers.get(name);
		if (ret==null) {
			Logger[] sLoggers = new Logger[loggers.length];
			for (int i=0; i<sLoggers.length; ++i) {
				sLoggers[i]=loggers[i].getLogger(name);
			}
			ret = new CompositeLogger(sLoggers);
			subLoggers.put(name, ret);
		}
		return  ret;
	}

	@Override
	public boolean isLoggable(Level level) {
		for (Logger logger: loggers) {
			if (logger.isLoggable(level)) {
				return true;
			}
		}
		return false;
	}

}
