package teetime;


import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import com.google.common.hash.HashCode;

import teetime.stage.MD5BruteforceStage;


public class Md5Benchmark {
	
	@State(Scope.Thread)
	public static class MyState {
        public HashCode a = MD5BruteforceStage.getMD5(0);
        public HashCode b = MD5BruteforceStage.getMD5(10);
        public byte[] a_bytes = a.asBytes();
        public byte[] b_bytes = b.asBytes();
        public MessageDigest md;        
        
        MyState()
        {
    		try {
    			this.md = MessageDigest.getInstance("MD5");
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		}
        }
    }
	
	@Benchmark
	@BenchmarkMode(Mode.AverageTime)
	@OutputTimeUnit(TimeUnit.NANOSECONDS)
    public int bruteforceHashCode0(MyState state) {
        return MD5BruteforceStage.bruteforce(state.a);
    }
	
	@Benchmark
	@BenchmarkMode(Mode.AverageTime)
	@OutputTimeUnit(TimeUnit.NANOSECONDS)
    public long bruteforceHashCode10(MyState state) {
        return MD5BruteforceStage.bruteforce(state.b);
    }
	
	@Benchmark
	@BenchmarkMode(Mode.AverageTime)
	@OutputTimeUnit(TimeUnit.NANOSECONDS)
    public long bruteforceByteArray0(MyState state) {
        return MD5BruteforceStage.bruteforce(state.md, state.a_bytes);
    }	
	
	@Benchmark
	@BenchmarkMode(Mode.AverageTime)
	@OutputTimeUnit(TimeUnit.NANOSECONDS)
    public long bruteforceByteArray10(MyState state) {
        return MD5BruteforceStage.bruteforce(state.md, state.b_bytes);
    }		
	
	public static void main(String[] args) throws RunnerException {
		URLClassLoader classLoader = (URLClassLoader) Md5Benchmark.class.getClassLoader();
		StringBuilder classpath = new StringBuilder();
		for(URL url : classLoader.getURLs())
		    classpath.append(url.getPath()).append(File.pathSeparator);
		System.setProperty("java.class.path", classpath.toString());
		
		
		Options options = new OptionsBuilder()
				.include(Md5Benchmark.class.getSimpleName())
				.forks(1)
				.build();

		new Runner(options).run();
	}

}

@@ -809,16 +809,224 @@
 k %7B%0D%0A%09%0D%0A
+%09private static MessageDigest createMessageDigest() %7B%0D%0A%09%09try %7B%0D%0A%09%09%09return MessageDigest.getInstance(%22MD5%22);%0D%0A%09%09%7D catch (NoSuchAlgorithmException e) %7B%0D%0A%09%09%09e.printStackTrace();%0D%0A%09%09%7D%0D%0A%09%09%0D%0A%09%09return null;%0D%0A%09%7D%0D%0A%09%0D%0A
 %09@State(
@@ -1318,217 +1318,33 @@
 t md
-;        %0D%0A        %0D%0A        MyState()%0D%0A        %7B%0D%0A    %09%09try %7B%0D%0A    %09%09%09this.md = MessageDigest.getInstance(%22MD5%22);%0D%0A    %09%09%7D catch (NoSuchAlgorithmException e) %7B%0D%0A    %09%09%09e.printStackTrace();%0D%0A    %09%09%7D%0D%0A        %7D
+ = createMessageDigest();
 %0D%0A  

state must have def ctor