/**
 * 
 */
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;

/**
 * Responsible for translating a {@link SyslogMessage} to {@link RawEvent}.
 * 
 * @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) {

		// Add facility
		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);
		
		Status status = getEventStatus(sm.getSeverity());
		e.setStatus(status);
		
		// Set the uniqueness of the event by hostname, facility, and message.
		// TBD: These fields need to be split out in a configuration file
		e.addFingerprintField("hostname");
		e.addFingerprintField("facility");
		e.addFingerprintField("message");
		
		// 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) {
				e.printStackTrace();
				LOG.error(e.getStackTrace().toString());
			}
		}
	}
}

@@ -89,153 +89,23 @@
 ava.
-text.DateFormat;%0Aimport java.text.SimpleDateFormat;%0Aimport java.util.Properties;%0Aimport java.util.TimeZone;%0A%0Aimport org.apache.camel.CamelContext
+util.Properties
 ;%0Aim
@@ -1517,16 +1517,54 @@
  event);
+%0A%09%09%0A%09%09LOG.debug(%22RawEvent: %22 + event);
 %0A%0A%09%09// S
@@ -2243,16 +2243,19 @@
 dress%0A%09%09
+// 
 e.getPro
@@ -2308,24 +2308,27 @@
 dress());%0A%09%09
+// 
 e.addTag(sm.
@@ -2495,16 +2495,56 @@
 ty);%0A%09%09%0A
+%09%09// Set event status based on Severity%0A
 %09%09Status
@@ -2997,57 +2997,84 @@
 ));%0A
-%09%09e.addProperty(%22timestamp%22,
+%0A%09%09// Set Title%0A%09%09e.setTitle(%22Syslog message from: %22 +
  sm.get
-Time
+Ho
 st
+n
 am
-p
+e
 ());%0A
+%09%09
 %0A%09%09/
@@ -3083,101 +3083,93 @@
 Set 
-Title%0A%09%09// TBD External configuration%0A%09%09e.setTitle(%22Syslog message from: %22 + sm.getHostname()
+Sender%0A%09%09e.getSender().setRef(%22Syslog%22);%0A%09%09e.getSender().setType(%22Boundary Event SDK%22
 );%0A%09

Add debug log for Raw Event ; Added Sender ; Removed remote address as an event property