/**
 * 
 */
package com.boundary.sdk.event.syslog;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.TimeZone;

import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.Processor;
import org.apache.camel.component.syslog.SyslogMessage;
import org.apache.camel.component.syslog.SyslogSeverity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boundary.sdk.event.RawEvent;
import com.boundary.sdk.event.Severity;
import com.boundary.sdk.event.Status;

/**
 * @author davidg
 * 
 */
public class SyslogToEventProcessor implements Processor {

	private static Logger LOG = LoggerFactory.getLogger(SyslogToEventProcessor.class);

	public SyslogToEventProcessor() {
	}
	
	private void logSyslogMessage(SyslogMessage slm) {
		LOG.debug(slm.getTimestamp()
				+ "|" + slm.getFacility()
				+ "|" + slm.getSeverity()
				+ "|" + slm.getHostname()
				+ "|" + slm.getRemoteAddress()
				+ "|" + slm.getLogMessage());
	}

	@Override
	public void process(Exchange exchange) throws Exception {
		Message message = exchange.getIn();

		// Extract SyslogMessage from the message body.
		SyslogMessage syslogMessage = (SyslogMessage) message.getBody(SyslogMessage.class);
		logSyslogMessage(syslogMessage);

		// Create new event to translate the syslog message to
		RawEvent event = new RawEvent();

		// Delegate to member method call to perform the translation
		syslogMessageToEvent(syslogMessage, event);

		// Set the message body to the RawEvent
		message.setBody(event, RawEvent.class);
	}

	/**
	 * Converts a {@link SyslogMessage} to {@link RawEvent}
	 * 
	 * @param sm
	 * @param e
	 */
	private void syslogMessageToEvent(SyslogMessage sm, RawEvent e) {

		e.getProperties().put("facility", sm.getFacility());
		e.addTag(sm.getFacility().toString());
		
		// Add the hostname
		e.getSource().setRef(sm.getHostname()).setType("host");
		e.getProperties().put("hostname", sm.getHostname());
		e.addTag(sm.getHostname());
		
		// Add the message
		e.setMessage(sm.getLogMessage());
		e.getProperties().put("message", sm.getLogMessage());
		
		// Add the remote address
		e.getProperties().put("remote_address", sm.getRemoteAddress());
		e.addTag(sm.getRemoteAddress());
		
		// Map the syslog severity to Boundary event severity
		Severity severity = getEventSeverity(sm.getSeverity());
		e.setSeverity(severity);
		e.addProperty("severity", sm.getSeverity().toString());
		e.addTag(sm.getSeverity().toString());
		
		Status status = getEventStatus(sm.getSeverity());
		e.setStatus(status);
		
		// Set the uniqueness of the event by hostname and facility
		// TBD These fields need to be split out in a configuration file
		e.addFingerprintField("hostname");
		e.addFingerprintField("facility");
		
		// Set the time at which the syslog record was created
		// TBD: Ensure time is in UTC
		e.setCreatedAt(sm.getTimestamp());
		e.addProperty("timestamp", sm.getTimestamp());

		// Set Title
		// TBD External configuration
		e.setTitle("Syslog Message from  " + sm.getHostname());
	}

	/**
	 * Set the Event from the severity in the Message
	 * 
	 * @param m
	 * @param e
	 */
	private Severity getEventSeverity(SyslogSeverity severity) {
		getProperties(severityMap,"syslog.severity.properties");
		String strSeverity = severityMap.getProperty(severity.toString());
		return Severity.valueOf(strSeverity);
	}
	
	/**
	 * 
	 * @param severity
	 * @return {@link Status}
	 */
	private Status getEventStatus(SyslogSeverity severity) {
		getProperties(statusMap,"syslog.status.properties");
		String strStatus = statusMap.getProperty(severity.toString());
		return Status.valueOf(strStatus);
	}


	private static Properties severityMap = new Properties();
	private static Properties statusMap = new Properties();

	public static void getProperties(Properties properties, String propertyFileName) {
		if (properties.isEmpty()) {
			try {
				properties.load(Thread.currentThread()
						.getContextClassLoader()
						.getResourceAsStream(propertyFileName));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				LOG.error(e.getStackTrace().toString());
			}
		}
	}
}

@@ -628,16 +628,96 @@
 s;%0A%0A/**%0A
+ * Responsible for translating a %7B@link SyslogMessage%7D to %7B@link RawEvent%7D.%0A * %0A
  * @auth
@@ -726,16 +726,16 @@
  davidg%0A
-
  * %0A */%0A
@@ -1904,16 +1904,34 @@
 t e) %7B%0A%0A
+%09%09// Add facility%0A
 %09%09e.getP
@@ -2810,12 +2810,9 @@
 name
- and
+,
  fac
@@ -2816,16 +2816,30 @@
 facility
+, and message.
 %0A%09%09// TB
@@ -2839,16 +2839,17 @@
 %09%09// TBD
+:
  These f
@@ -2973,16 +2973,52 @@
 lity%22);%0A
+%09%09e.addFingerprintField(%22message%22);%0A
 %09%09%0A%09%09// 
@@ -3256,17 +3256,17 @@
 %22Syslog 
-M
+m
 essage f
@@ -3268,17 +3268,17 @@
 age from
- 
+:
  %22 + sm.

Add javdoc ; Change title casing ; added Syslog message to the fingerprint fields of the RawEvent