package org.etsi.common.logging;


import org.etsi.common.MiscTools;

public class LoggingInterface {
	
	public enum LogLevel {
		//ORDER MATTERS
		ERROR,
		WARNING,
		INFORMATION,
		FIXME,
		DEBUG;
	}

	public enum MessageClass {
		//ORDER MATTERS
		UNIVERSAL ("Universal", 0),
		GENERAL ("General", 1),
		NAMING ("Naming Conventions", 2),
		DOCUMENTATION ("Code Documentation", 3),
		LOGGING ("Log Statements", 4),
		STRUCTURE ("Structure of Data", 5), 
		STYLE ("Code Style", 6),
		MODULARIZATION ("Test Suite Modularization", 7);
		
		private final String description;
		private final int id;
		private int occurenceCount = 0;
		
		MessageClass (String description, int id){
			this.description = description;
			this.id = id;
		}

		public String getDescription() {
			return description;
		}

		public int getId() {
			return id;
		}

		public void addOccurence() {
			this.occurenceCount++;
		}

		public int getOccurenceCount() {
			return occurenceCount;
		}
	}
	
	private String logSourceName = "";
	private LogLevel maximumLogLevel = LogLevel.INFORMATION;
	private LogLevel defaultLogLevel = LogLevel.INFORMATION;
	private LoggingConfiguration configuration = new LoggingConfiguration();
	
	public LoggingInterface(LoggingConfiguration logConfiguration) {
		this.setConfiguration(logConfiguration);
	}
	
	public LoggingInterface(String logSourceName, LoggingConfiguration logConfiguration){
		this(logConfiguration);
		this.setLogSourceName(logSourceName);
	}
	public LoggingInterface(String logSourceName, LoggingConfiguration logConfiguration, LogLevel maximumLogLevel){
		this(logSourceName, logConfiguration);
		this.setMaximumLogLevel(maximumLogLevel);
	}
	
	private LogMessage createLogMessage(LogLevel l, int startLine, int endLine, MessageClass messageClass, String message, String details){
		LogMessage logMessage = new LogMessage();
		logMessage.setPrefix(this.getConfiguration().getLogOutputPrefix());

		if (this.getConfiguration().isShowFullPath()) {
			logMessage.setFilename(this.getLogSourceName());
		} else {
			if (this.getConfiguration().isShowFilename()) {
				logMessage.setFilename(MiscTools.getShortFilename(this
						.getLogSourceName()));
			}
		}
		logMessage.setStartLine(startLine);
		logMessage.setEndLine(endLine);
		logMessage.setLogLevel(l);
		
		messageClass.addOccurence();
		
		if (this.getConfiguration().isShowMessageClass()) {
			logMessage.setMessageClass(messageClass);
		} else {
			logMessage.setMessageClass(null);
		}
		
		logMessage.setMessage(message);

		if (this.getConfiguration().isShowDetails() && details != null) {
			logMessage.setDetails(details);
		} else {
			logMessage.setDetails(null);
		}
		
		return logMessage;
	}
	
/*	private String composeLogMessage(LogLevel l, int startLine, int endLine, MessageClass messageClass, String message, String details){
		String composedLogMessage = "";

		composedLogMessage += this.getConfiguration().getLogOutputPrefix();

		if (this.getConfiguration().isShowFullPath()) {
			composedLogMessage += this.getLogSourceName() + ": ";
		} else {
			if (this.getConfiguration().isShowFilename()) {
				composedLogMessage += MiscTools.getShortFilename(this
						.getLogSourceName())
						+ ": ";
			}
		}

		if (startLine >= endLine) {
			composedLogMessage += startLine + ": ";
		} else {
			composedLogMessage += startLine + "-" + endLine + ": ";
		}

		composedLogMessage += l + ": ";

		if (this.getConfiguration().isShowMessageClass()) {
			composedLogMessage += messageClass.getDescription() + ": ";
		}

		composedLogMessage += message;

		if (this.getConfiguration().isShowDetails() && details != null) {
			composedLogMessage += "(" + details + ")";
		}

		return composedLogMessage;
	}
*/

	public void logMessage(LogLevel l, int startLine, int endLine, MessageClass messageClass, String message, String details){
		if (showLogLevel(l)){
			LogMessage composedLogMessage = createLogMessage(l, startLine, endLine, messageClass, message, details);
			outputLog(composedLogMessage);
		}
	}
	
	public void logMessage(LogLevel l, int startLine, int endLine, MessageClass messageClass, String message){
		if (showLogLevel(l)){
			LogMessage composedLogMessage = createLogMessage(l, startLine, endLine, messageClass, message, null);
			outputLog(composedLogMessage);
		}
	}

	public void logMessage(int startLine, int endLine, MessageClass messageClass, String message, String details){
		if (showLogLevel(this.getDefaultLogLevel())){
			LogMessage composedLogMessage = createLogMessage(this.getDefaultLogLevel(), startLine, endLine, messageClass, message, details);
			outputLog(composedLogMessage);
		}
	}

	
	public void logMessage(int startLine, int endLine, MessageClass messageClass, String message){
		if (showLogLevel(this.getDefaultLogLevel())){
			LogMessage composedLogMessage = createLogMessage(this.getDefaultLogLevel(), startLine, endLine, messageClass, message, null);
			outputLog(composedLogMessage);
		}
	}

	
//	private void outputLog(String composedLogMessage){
//		System.out.println(composedLogMessage);
//	}

	private void outputLog(LogMessage composedLogMessage){
		System.out.println(composedLogMessage.toString());
	}

	public void logWarning(int startLine, int endLine, MessageClass messageClass, String message){
		if (showLogLevel(LogLevel.WARNING)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.WARNING, startLine, endLine, messageClass, message, null);
			outputLog(composedLogMessage);
		}
	}

	public void logWarning(int startLine, int endLine, MessageClass messageClass, String message, String details){
		if (showLogLevel(LogLevel.WARNING)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.WARNING, startLine, endLine, messageClass, message, details);
			outputLog(composedLogMessage);
		}
		
	}
	
	public void logDebug(int startLine, int endLine, MessageClass messageClass, String message){
		if (showLogLevel(LogLevel.DEBUG)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.DEBUG, startLine, endLine, messageClass, message, null);
			outputLog(composedLogMessage);
		}
		
	}
	
	public void logDebug(int startLine, int endLine, MessageClass messageClass, String message, String details){
		if (showLogLevel(LogLevel.DEBUG)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.DEBUG, startLine, endLine, messageClass, message, details);
			outputLog(composedLogMessage);
		}
		
	}

	public void logFix(int startLine, int endLine, MessageClass messageClass, String message){
		if (showLogLevel(LogLevel.FIXME)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.FIXME, startLine, endLine, messageClass, message, null);
			outputLog(composedLogMessage);
		}
		
	}
	
	public void logFix(int startLine, int endLine, MessageClass messageClass, String message, String details){
		if (showLogLevel(LogLevel.FIXME)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.FIXME, startLine, endLine, messageClass, message, details);
			outputLog(composedLogMessage);
		}
		
	}

	
	public void logError(int startLine, int endLine, MessageClass messageClass, String message){
		if (showLogLevel(LogLevel.ERROR)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.ERROR, startLine, endLine, messageClass, message, null);
			outputLog(composedLogMessage);
		}
	}
	
	public void logInformation(int startLine, int endLine, MessageClass messageClass, String message){
		if (showLogLevel(LogLevel.INFORMATION)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.INFORMATION, startLine, endLine, messageClass, message, null);
			outputLog(composedLogMessage);
		}
	}

	public void logInformation(int startLine, int endLine, MessageClass messageClass, String message, String detail){
		if (showLogLevel(LogLevel.INFORMATION)){
			LogMessage composedLogMessage = createLogMessage(LogLevel.INFORMATION, startLine, endLine, messageClass, message, detail);
			outputLog(composedLogMessage);
		}
	}

	
	public String getLogSourceName() {
		return logSourceName;
	}
	
		
	public void setMaximumLogLevel(LogLevel maximumLogLevel) {
		this.maximumLogLevel = maximumLogLevel;
	}
	
	public LogLevel getMaximumLogLevel() {
		return maximumLogLevel;
	}

	public boolean showLogLevel(LogLevel logLevel) {
		boolean show = false;
		if (logLevel.ordinal() <= this.getMaximumLogLevel().ordinal()){
			show = true;
		}
		return show;
	}

	public void setConfiguration(LoggingConfiguration configuration) {
		this.configuration = configuration;
	}
	public LoggingConfiguration getConfiguration() {
		return configuration;
	}
	public void setDefaultLogLevel(LogLevel defaultLogLevel) {
		this.defaultLogLevel = defaultLogLevel;
	}
	public LogLevel getDefaultLogLevel() {
		return defaultLogLevel;
	}
	public void setLogSourceName(String logSourceName) {
		this.logSourceName = logSourceName;
	}


	
}
