// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.consoleproxy.util;

// logger facility for dynamic switch between console logger used in Applet and log4j based logger
public class Logger {
	private static LoggerFactory factory = null;
	
	public static final int LEVEL_TRACE = 1;
	public static final int LEVEL_DEBUG = 2;
	public static final int LEVEL_INFO = 3;
	public static final int LEVEL_WARN = 4;
	public static final int LEVEL_ERROR = 5;
	
	private Class<?> clazz;
	private Logger logger;
	
	private static int level = LEVEL_INFO;
	
	public static Logger getLogger(Class<?> clazz) {
		return new Logger(clazz);
	}
	
	public static void setFactory(LoggerFactory f) {
		factory = f;
	}
	
	public static void setLevel(int l) {
		level = l;
	}
	
	public Logger(Class<?> clazz) {
		this.clazz = clazz;
	}
	
	protected Logger() {
	}
	
	public boolean isTraceEnabled() {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			return logger.isTraceEnabled();
		}
		return level <= LEVEL_TRACE;
	}
	
	public boolean isDebugEnabled() {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			return logger.isDebugEnabled();
		}
		return level <= LEVEL_DEBUG;
	}
	
	public boolean isInfoEnabled() {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			return logger.isInfoEnabled();
		}
		return level <= LEVEL_INFO;
	}

	public void trace(Object message) {
		
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.trace(message);
		} else {
			if(level <= LEVEL_TRACE)
				System.out.println(message);
		}
	}
	
	public void trace(Object message, Throwable exception) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.trace(message, exception);
		} else {
			if(level <= LEVEL_TRACE) {
				System.out.println(message);
				if (exception != null) {
					exception.printStackTrace(System.out);
				}
			}
		}
	}
	
	public void info(Object message) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.info(message);
		} else {
			if(level <= LEVEL_INFO)
				System.out.println(message);
		}
	}
	
	public void info(Object message, Throwable exception) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.info(message, exception);
		} else {		
			if(level <= LEVEL_INFO) {
				System.out.println(message);
				if (exception != null) {
					exception.printStackTrace(System.out);
				}
			}
		}
	}
	
	public void debug(Object message) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.debug(message);
		} else {
			if(level <= LEVEL_DEBUG)
				System.out.println(message);
		}
	}
	
	public void debug(Object message, Throwable exception) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.debug(message, exception);
		} else {
			if(level <= LEVEL_DEBUG) {
				System.out.println(message);
				if (exception != null) {
					exception.printStackTrace(System.out);
				}
			}
		}
	}
	
	public void warn(Object message) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.warn(message);
		} else {
			if(level <= LEVEL_WARN)
				System.out.println(message);
		}
	}
	
	public void warn(Object message, Throwable exception) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.warn(message, exception);
		} else {
			if(level <= LEVEL_WARN) {
				System.out.println(message);
				if (exception != null) {
					exception.printStackTrace(System.out);
				}
			}
		}
	}
	
	public void error(Object message) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.error(message);
		} else {
			if(level <= LEVEL_ERROR)
				System.out.println(message);
		}
	}
	
	public void error(Object message, Throwable exception) {
		if(factory != null) {
			if(logger == null)
				logger = factory.getLogger(clazz);
			
			logger.error(message, exception);
		} else {
			if(level <= LEVEL_ERROR) {
				System.out.println(message);
				if (exception != null) {
					exception.printStackTrace(System.out);
				}
			}
		}
	}
}
