package com.eqot.xray.processor;

import com.squareup.javapoet.ClassName;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;

@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class ClassDef {
    final ClassName className;
    final List<MethodDef> constructors = new ArrayList<>();
    final List<MethodDef> methods = new ArrayList<>();

    ClassDef(String target) {
        className = ClassName.bestGuess(target);

        Class clazz = null;
        try {
            clazz = Class.forName(target);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        if (clazz == null) {
            return;
        }

        for (Constructor constructor : clazz.getDeclaredConstructors()) {
            MethodDef methodDef = new MethodDef(constructor);
            constructors.add(methodDef);
        }

        for (Method method : clazz.getDeclaredMethods()) {
            MethodDef methodDef = new MethodDef(method);
            methods.add(methodDef);
        }
    }

    public class MethodDef {
        final String name;
        final boolean isStatic;
        final Class<?> returnType;
        final List<ParameterDef> parameters = new ArrayList<>();

        MethodDef(Method method) {
            name = method.getName();
            returnType = method.getReturnType();
            isStatic = (method.getModifiers() & Modifier.STATIC) != 0;

            addParameters(method.getParameters());
        }

        MethodDef(Constructor constructor) {
            name = constructor.getName();
            returnType = null;
            isStatic = false;

            addParameters(constructor.getParameters());
        }

        private void addParameters(Parameter[] parameters) {
            for (Parameter parameter : parameters) {
                ParameterDef parameterDef = new ParameterDef(parameter);
                this.parameters.add(parameterDef);
            }
        }
    }

    public class ParameterDef {
        final Class<?> type;
        final String name;

        ParameterDef(Parameter parameter) {
            type = parameter.getType();
            name = parameter.getName();
        }
    }
}

@@ -106,16 +106,48 @@
 ructor;%0A
+import java.lang.reflect.Field;%0A
 import j
@@ -171,16 +171,16 @@
 Method;%0A
-
 import j
@@ -607,24 +607,77 @@
 rayList%3C%3E();
+%0A    final List%3CFieldDef%3E fields = new ArrayList%3C%3E();
 %0A%0A    ClassD
@@ -1320,32 +1320,186 @@
 dDef);%0A        %7D
+%0A%0A        for (Field field : clazz.getDeclaredFields()) %7B%0A            FieldDef fieldDef = new FieldDef(field);%0A            fields.add(fieldDef);%0A        %7D
 %0A    %7D%0A%0A    publ
@@ -2584,32 +2584,32 @@
 eter.getType();%0A
-
             name
@@ -2647,11 +2647,217 @@
  %7D%0A    %7D
+%0A%0A    public class FieldDef %7B%0A        final Class%3C?%3E type;%0A        final String name;%0A%0A        FieldDef(Field field) %7B%0A            type = field.getType();%0A            name = field.getName();%0A        %7D%0A    %7D
 %0A%7D%0A

Add FieldDef