/*
 * Copyright 2015 JKOOL, LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with 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.
 */
package com.jkool.jesl.net.syslogd;

import java.io.PrintStream;
import java.net.SocketAddress;
import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.StringEscapeUtils;
import org.productivity.java.syslog4j.impl.message.structured.StructuredSyslogMessage;
import org.productivity.java.syslog4j.server.SyslogServerEventIF;
import org.productivity.java.syslog4j.server.SyslogServerIF;
import org.productivity.java.syslog4j.server.impl.event.printstream.PrintStreamSyslogServerEventHandler;
import org.productivity.java.syslog4j.server.impl.event.structured.StructuredSyslogServerEvent;
import org.productivity.java.syslog4j.util.SyslogUtility;

/**
 * This class implements simple syslog event handler that outputs
 * formatted syslog messages to a print stream.
 *
 * @version $Revision $
 */
class JsonSyslogServerEventHandler extends PrintStreamSyslogServerEventHandler {
    private static final long serialVersionUID = 8964244723777923472L;

	public JsonSyslogServerEventHandler(PrintStream out) {
		super(out);
	}
	
	@Override
	public void event(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, SyslogServerEventIF event) {
		String date = (event.getDate() == null ? new Date() : event.getDate()).toString();
		String facility = SyslogTNT4JEventHandler.getFacilityString(event.getFacility());
		String level = SyslogUtility.getLevelString(event.getLevel());
		String host = event.getHost();
		if (!(event instanceof StructuredSyslogServerEvent)) {
			this.stream.println("{\"host\":\"" + host
					+ "\", \"facility\":\"" + facility
					+ "\", \"timestamp\":\"" + date
					+ "\", \"level\":\"" + level
					+ "\", \"msg\":\"" + StringEscapeUtils.escapeJson(event.getMessage()) 
					+ "\"}");
		} else {
			StructuredSyslogServerEvent sevent = (StructuredSyslogServerEvent) event;
			StructuredSyslogMessage sm = sevent.getStructuredMessage();
			Map<?, ?> arttrs = sm.getStructuredData();
			this.stream.println("{\"host\":\"" + host
					+ "\", \"facility\":\"" + facility
					+ "\", \"timestamp\":\"" + date
					+ "\", \"appl\":\"" + sevent.getApplicationName()
					+ "\", \"pid\":" + (sevent.getProcessId() != null && sevent.getProcessId().isEmpty()? 0: sevent.getProcessId())
					+ ", \"level\":\"" + level
					+ "\", \"map.size\":" + ((arttrs != null)? arttrs.size(): 0)
					+ ", \"msg\":\"" + StringEscapeUtils.escapeJson(event.getMessage()) 
					+ "\"}");
		}
	}	
}
@@ -781,16 +781,110 @@
 eUtils;%0A
+import org.joda.time.format.DateTimeFormatter;%0Aimport org.joda.time.format.ISODateTimeFormat;%0A
 import o
@@ -1466,16 +1466,174 @@
  stream.
+ The output contains%0A * offset.usec which is time since last event in microseconds. This field%0A * can be used to play back events in exact same time sequence.
 %0A *%0A * @
@@ -1809,16 +1809,122 @@
 3472L;%0A%0A
+    private long lastEvent = 0;%0A%09DateTimeFormatter fmt = ISODateTimeFormat.dateTime().withZoneUTC();%0A    %0A
 %09public 
@@ -2125,22 +2125,147 @@
 nt) %7B%0A%09%09
-String
+long now = System.nanoTime();%0A%09%09long offset = lastEvent == 0? 0: (System.nanoTime() - lastEvent)/1000;%0A%09%09lastEvent = now;%0A%09%09%0A%09%09Date
  date = 
@@ -2324,20 +2324,60 @@
 e())
-.to
+;%0A%09%09
 String
-();
+ timestamp = fmt.print(date.getTime());%0A%09%09
 %0A%09%09S
@@ -2629,32 +2629,69 @@
 tream.println(%22%7B
+%5C%22offset.usec%5C%22:%22 + offset%0A%09%09%09%09%09+ %22, 
 %5C%22host%5C%22:%5C%22%22 + h
@@ -2758,36 +2758,41 @@
 mestamp%5C%22:%5C%22%22 + 
-date
+timestamp
 %0A%09%09%09%09%09+ %22%5C%22, %5C%22l
@@ -3123,16 +3123,53 @@
 intln(%22%7B
+%5C%22offset.usec%5C%22:%22 + offset%0A%09%09%09%09%09+ %22, 
 %5C%22host%5C%22
@@ -3252,20 +3252,25 @@
 %22:%5C%22%22 + 
-date
+timestamp
 %0A%09%09%09%09%09+ 

use ISO8601 timestamp, include offset since last event in usec