package diagent;

import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;

import java.io.IOException;
import java.lang.instrument.Instrumentation;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.agent.builder.AgentBuilder.InitializationStrategy;
import net.bytebuddy.agent.builder.AgentBuilder.Transformer;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.DynamicType.Builder;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.matcher.ElementMatchers;

public class DIAgent {

	private static final String AUTOWIRED_ANNOTATION = "org.springframework.beans.factory.annotation.Autowired";
	private static final String INJECT_ANNOTATION = "javax.inject.Inject";

	public static void premain(String args, Instrumentation instrumentation) throws IOException {

		System.out.println("Hello World from Agent");

		new DependencyGraphWebServer(9090).start();

		new AgentBuilder.Default().withListener(new AgentListener())
				.withInitializationStrategy(InitializationStrategy.Premature.INSTANCE)

				.type(ElementMatchers.not(ElementMatchers.nameStartsWith("java"))).transform(new Transformer() {

					@Override
					public Builder<?> transform(Builder<?> builder, TypeDescription typeDescription) {

						return builder
								.invokable(isAnnotatedWith(ElementMatchers.named(
										INJECT_ANNOTATION)).or(isAnnotatedWith(
												ElementMatchers.named(AUTOWIRED_ANNOTATION))))
								.intercept(SuperMethodCall.INSTANCE
										.andThen(MethodDelegation.to(InjectionInterceptor.class)));
					}
				}).installOn(instrumentation);
	}
}

class AgentListener implements AgentBuilder.Listener {

	@Override
	public void onComplete(String arg0) {
	}

	@Override
	public void onError(String typeName, Throwable throwable) {
//		System.err.println("Error for " + typeName);
//		throwable.printStackTrace();
	}

	@Override
	public void onIgnored(TypeDescription arg0) {
	}

	@Override
	public void onTransformation(TypeDescription arg0, DynamicType arg1) {
	}

}

@@ -137,30 +137,176 @@
 trument.
-Instrumentatio
+ClassFileTransformer;%0Aimport java.lang.instrument.IllegalClassFormatException;%0Aimport java.lang.instrument.Instrumentation;%0Aimport java.security.ProtectionDomai
 n;%0A%0Aimpo
@@ -811,191 +811,9 @@
 t %7B%0A
-%0A%09private static final String AUTOWIRED_ANNOTATION = %22org.springframework.beans.factory.annotation.Autowired%22;%0A%09private static final String INJECT_ANNOTATION = %22javax.inject.Inject%22;%0A
+%09
 %0A%09pu
@@ -886,27 +886,8 @@
 ion)
- throws IOException
  %7B%0A%0A
@@ -938,55 +938,147 @@
 %22);%0A
+%09%09
 %0A%09%09
-new DependencyGraphWebServer(9090).start();%0A
+startWebServer();%0A%09%09%0A%09%09transformClasses(instrumentation);%0A%09%7D%0A%0A%09private static void transformClasses(Instrumentation instrumentation) %7B
 %0A%09%09n
@@ -1497,27 +1497,16 @@
 s.named(
-%0A%09%09%09%09%09%09%09%09%09%09
 INJECT_A
@@ -1516,16 +1516,27 @@
 TATION))
+%0A%09%09%09%09%09%09%09%09%09%09
 .or(isAn
@@ -1551,21 +1551,8 @@
 ith(
-%0A%09%09%09%09%09%09%09%09%09%09%09%09
 Elem
@@ -1752,16 +1752,355 @@
 ion);%0A%09%7D
+%0A%0A%09private static void startWebServer() %7B%0A%09%09try %7B%0A%09%09%09new DependencyGraphWebServer(9090).start();%0A%09%09%7D catch (IOException e) %7B%0A%09%09%09e.printStackTrace();%0A%09%09%7D%0A%09%7D%0A%09%0A%09private static final String AUTOWIRED_ANNOTATION = %22org.springframework.beans.factory.annotation.Autowired%22;%0A%09private static final String INJECT_ANNOTATION = %22javax.inject.Inject%22;
 %0A%7D%0A%0Aclas
@@ -2277,20 +2277,21 @@
 able) %7B%0A
-//
 %09%09
+// 
 System.e
@@ -2331,12 +2331,13 @@
 e);%0A
-//
 %09%09
+// 
 thro

refactor premain