package com.github.aureliano.defero.profile;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import java.util.Properties;

public class Profiler {

	private static final double MEM_FACTOR = 1024.0 * 1024.0; // MiB
	private static final DecimalFormat DECIMAL_FORMAT;
	
	static {
		DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
		symbols.setDecimalSeparator('.');
		symbols.setGroupingSeparator(',');
		
		DECIMAL_FORMAT = new DecimalFormat("##0.00", symbols);
	}
	
	private long time;
	private int availableProcessors;
	private double freeMemory;
	private double maxMemory;
	private double totalMemory;
	
	public Profiler() {
		super();
	}
	
	public void start() {
		this.time = System.currentTimeMillis();
		
		Runtime runtime = Runtime.getRuntime();
		this.availableProcessors = runtime.availableProcessors();
		this.freeMemory = runtime.freeMemory();
		this.maxMemory = runtime.maxMemory();
		this.totalMemory = runtime.totalMemory();
	}
	
	public Profiler stop() {
		Profiler profiler = new Profiler();
		
		profiler.time = System.currentTimeMillis();
		profiler.availableProcessors = this.availableProcessors;
		profiler.freeMemory = Runtime.getRuntime().freeMemory();
		profiler.maxMemory = this.maxMemory;
		profiler.totalMemory = this.totalMemory;
		
		return profiler;
	}
	
	public static Profiler diff(Profiler p1, Profiler p2) {
		Profiler profiler = new Profiler();
		
		profiler.time = p2.time - p1.time;
		profiler.availableProcessors = p1.availableProcessors;
		profiler.freeMemory = p1.freeMemory - p2.freeMemory;
		profiler.maxMemory = p1.maxMemory;
		profiler.totalMemory = p1.totalMemory;
		
		return profiler;
	}
	
	public static Properties parse(Profiler profiler) {
		Properties properties = new Properties();
		
		properties.put("profile.time.elapsed", formatTime(profiler.time));
		properties.put("profile.processor.available", String.valueOf(profiler.availableProcessors));
		properties.put("profile.memory.free", DECIMAL_FORMAT.format(profiler.freeMemory / MEM_FACTOR) + " MiB");
		properties.put("profile.memory.max", DECIMAL_FORMAT.format(profiler.maxMemory / MEM_FACTOR) + " MiB");
		properties.put("profile.memomry.total", DECIMAL_FORMAT.format(profiler.totalMemory / MEM_FACTOR) + " MiB");
		
		return properties;
	}
	
	private static String formatTime(long t) {
		if (t < 1000) {
			return t + " ms";
		} else if (t > 1000 && t < 60000) {
			return t / 1000 + " sec";
		} else {
			return t / 1000 / 60 + " min";
		}
	}

	public long getTime() {
		return time;
	}

	public int getAvailableProcessors() {
		return availableProcessors;
	}

	public double getFreeMemory() {
		return freeMemory;
	}

	public double getMaxMemory() {
		return maxMemory;
	}

	public double getTotalMemory() {
		return totalMemory;
	}
}
@@ -163,16 +163,54 @@
 perties;
+%0Aimport java.util.concurrent.TimeUnit;
 %0A%0Apublic
@@ -2399,32 +2399,18 @@
 ong 
-t) %7B%0A%09%09if (t %3C 1000
+millis
 ) %7B%0A
-%09
 %09%09re
@@ -2418,134 +2418,206 @@
 urn 
-t + %22 ms%22;%0A%09%09%7D else if (t %3E 1000 && t %3C 60000) %7B%0A%09%09%09return t / 1000 + %22 sec%22;%0A%09%09%7D else %7B%0A%09%09%09return t / 1000 / 60 + %22 min%22;%0A%09%09%7D
+String.format(%22%25d min, %25d sec%22, %0A%09%09%09TimeUnit.MILLISECONDS.toMinutes(millis),%0A%09%09%09TimeUnit.MILLISECONDS.toSeconds(millis) - %0A%09%09%09TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))%0A%09%09);
 %0A%09%7D%0A

Fix time formatter.