

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import oracle.jrockit.jfr.parser.ChunkParser;
import oracle.jrockit.jfr.parser.FLREvent;
import oracle.jrockit.jfr.parser.Parser;

public class StrangeTimes {

	public static void main(String... args) throws IOException {
		if (args.length == 0) {
			System.out.println("To print time stamps for a recording file and start and end events do:");
			System.out.println("java StrangeTimes file.jfr");
			System.out.println();
			System.out.println("To print time stamps for recording and all events do:");
			System.out.println("java StrangeTimes file.jfr all");
			return;
		}
		String fileName = args[0];
		boolean all = false;
		if (args.length> 1) {
			all = args[1].equals("all");
		}
		Parser p = new Parser(fileName);
		
		int chunkNumber = 1;
		long min_s = Long.MAX_VALUE;
		long max_s = Long.MIN_VALUE;
		for (ChunkParser cp : p) {
			long s_millis = cp.getStartTimestampMillis();
			long e_millis = cp.getEndTimestampMillis();
			min_s = Math.max(s_millis, min_s);
			max_s = Math.max(s_millis, max_s);
			Date start = new Date(s_millis);
			Date end = new Date(e_millis);
			System.out.println("Chunk " + chunkNumber);
			System.out.println("============================");
			System.out.println("Chunk Start: " + start);
			System.out.println("Chunk End: " + end);
			System.out.println("Chunk Duration: " + (e_millis - s_millis) / 1000.0 + " s");
			long first_e = Long.MAX_VALUE;
			long last_e = Long.MIN_VALUE;
			List<FLREvent> allEvents = new ArrayList<>();
			for (FLREvent event : cp) {
				long es = event.getStartTime();
				if (es != 0) {
					first_e = Math.min(first_e, es);
				}
				last_e = Math.max(last_e, event.getTimestamp());
				allEvents.add(event);
			}
			Collections.sort(allEvents, (x, y) -> {
				return Long.compare(x.getTimestamp(), y.getTimestamp());
			});
			System.out.println("Events:");
			if (all) {
				for (FLREvent e : allEvents) {
					printEvent(cp, e);
				}
			} else {
				for (int i = 0; i < 5; i++) {
					printEvent(cp, allEvents.get(i));
				}
				System.out.println("...");
				for (int i = allEvents.size() - 5; i < allEvents.size(); i++) {
					printEvent(cp, allEvents.get(i));
				}
			}

			long first_e_millis = cp.ticksToMillis(first_e - cp.getStartTimeStampTicks()) + s_millis;
			long last_e_millis = cp.ticksToMillis(last_e - cp.getStartTimeStampTicks()) + s_millis;
			System.out.println("First Event start: " + new Date(first_e_millis));
			System.out.println("Last Event end: " + new Date(last_e_millis));
			System.out.println("Event span: " + (last_e_millis - first_e_millis) / 1000.0 + " s");
			chunkNumber++;
			System.out.println();
		}
		p.close();
	}

	private static void printEvent(ChunkParser cp, FLREvent e) {
		String name = e.getName();
		long endTicks = e.getTimestamp();
		long startTicks = e.getStartTime();
		if (startTicks == 0) {
			startTicks = endTicks;
		}
		long ticksDelta = startTicks - cp.getStartTimeStampTicks();
		long startMillis = cp.getStartTimestampMillis() + cp.ticksToMillis(ticksDelta);
		ticksDelta = endTicks - cp.getStartTimeStampTicks();
		long endMills = cp.getStartTimestampMillis() + cp.ticksToMillis(ticksDelta);
		System.out.println(name + " " + new Date(startMillis) + " - " + new Date(endMills));

	}
}
