/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/ 
package gov.va.med.esr.service;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import gov.va.med.fw.service.AbstractComponent;
import gov.va.med.fw.service.trigger.Log4jTriggerEvent;
import gov.va.med.fw.service.trigger.TriggerEvent;
import gov.va.med.fw.util.SystemUtils;


/**
* Log4jConfigService
* 
* @author Venky Kullampalle
* @version 1.0
*/
public class Log4jConfigService extends AbstractComponent {
	
	protected Log logger = LogFactory.getLog(SystemUtils.ALWAYS_LOGGER);	
	
	// Deafult log levels from log4j xml file.
	private Map loggerLogLevels=null;
	
	/**
	 * This method caches default log levels.
	 *
	 */
	public void init()
	{
		loggerLogLevels=new HashMap();
		Enumeration loggers = LogManager.getCurrentLoggers();				
		while (loggers.hasMoreElements()) {
			Logger logger = (Logger) loggers.nextElement();
			// Cache only esr loggers log levels.
			if(logger.getName().startsWith("gov"))
			{
				loggerLogLevels.put(logger.getName(),logger.getEffectiveLevel().toString().toLowerCase());				
			}
		}

		logger.info("Cached : " + loggerLogLevels.size()+ " Logger log default levels.");				
	}
	
	/**
	 * This method updates the log level.
	 * @param triggerEvent
	 */

	public void updateLogLevel(TriggerEvent triggerEvent)
	{
		//If default log leves map is null, call init method cache log levels.
		// These default log levels are used to reset it to default levels.
		if(loggerLogLevels==null)
			init();
		Log4jTriggerEvent log4jTriggerEvent=(Log4jTriggerEvent)triggerEvent;
		Map logLevels=null;
		
		//If it is an update trigger event type update the passed loggers with passed log levels.
		if(Log4jTriggerEvent.UPDATE.equals(log4jTriggerEvent.getTriggerEventType()))
		{
			Object [] payLoad=(Object []) log4jTriggerEvent.getPayload();
			logLevels=payLoad!=null && payLoad.length>0?(Map)payLoad[0]:null;
			//If is reset to default trigger event type, reset logger log levels to default levels
			// using cahed values.
		}else if(Log4jTriggerEvent.RESET_TO_DEFAULT.equals(log4jTriggerEvent.getTriggerEventType()))
		{
			//reset it to default log levels.
			logLevels=this.loggerLogLevels;
		}
		updateLogLevel(logLevels);
	}
	
	/**
	 * This method updates the log level.
	 * @param logConfig
	 */
	public void updateLogLevel(Map logConfigs)
	{
		Logger selectedLogger=null;
		int noLoggers=0;
		//If map is null do not do anything.
		if (logConfigs==null)
		{
			return;
		}
		// Loop through the map and update the logger log levels, if they are different.
		for (Iterator it=logConfigs.keySet().iterator(); it.hasNext();)
		{
			
			String loggerName=(String)it.next();
			String logLevel=(String)logConfigs.get(loggerName);
			selectedLogger = LogManager.getLogger(loggerName);
			Level currentLevel=selectedLogger.getEffectiveLevel();
			// If current log level is different from passed log level
			// update the log level of passed logger.
			if(!currentLevel.toString().equalsIgnoreCase(logLevel))
			{
		        selectedLogger.setLevel(Level.toLevel(logLevel));
		        noLoggers++;

				logger.info("Updated Logger: " + loggerName+ " from log level "
						+currentLevel+"  to log level "+logLevel.toUpperCase());				
			}
		} 
		logger.info("Updated : " + noLoggers+ " Logger log levels.");				
	} 
}
