package editor.wordcount;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.function.Supplier;

public class TimeTest {
	private String[] words;
	
	public static String file2String(File file) throws UnsupportedEncodingException, IOException {
		return new String(Files.readAllBytes(file.toPath()), "UTF8");
	}
	
	public TimeTest(String filename) throws UnsupportedEncodingException, IOException {
		words = file2String(new File(filename)).split("\\s+");
	}
	
	public void runTest(WordCounter obj) {
		System.out.println("Testing " + obj.getClass().getCanonicalName());
		long duration = getTestDurationFor(obj, true);
		System.out.println("duration: " + duration + " ms");
	}
	
	public long getTestDurationFor(WordCounter obj, boolean printTotal) {
		long start = System.currentTimeMillis();
		for (String word: words) {
			obj.bump(word);
		}
		int total = 0;
		for (WordCounterEntry entry: obj) {
			total += entry.getCount();
		}
		if (printTotal) System.out.println("total words: " + total);
		return System.currentTimeMillis() - start;
	}
	
	public void runMany(Supplier<WordCounter> cons, int trials) {
		ArrayList<Long> durations = new ArrayList<Long>();
		for (int i = 0; i < trials; i++) {
			durations.add(getTestDurationFor(cons.get(), false));
		}
		long total = durations.stream().reduce(0L, (x, y) -> x + y);
		double mean = (double)total / trials;
		double ssd = durations.stream().mapToDouble(x -> Math.pow(x - mean, 2.0)).sum();
		double stdDev = Math.sqrt(ssd / trials);
		System.out.println(cons.get().getClass() + ": " + mean + " +/- " + stdDev + " ms");
	}
	
	public static void main(String[] args) throws UnsupportedEncodingException, IOException {
		TimeTest tester = new TimeTest("MobyDick.txt");
		tester.runTest(new ArrayWordCounter());
		tester.runTest(new SortedArrayWordCounter());
	}
}
