package com.kiselev.reflection.ui.annotation;

import com.kiselev.reflection.ui.indent.IndentUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AnnotationsUtils {

    public String getAnnotations(AnnotatedElement annotatedElement) {
        String annotations = "";

        String indent = new IndentUtils().getIndent(annotatedElement);

        for (Annotation annotation : annotatedElement.getAnnotations()) {
            annotations += indent + getAnnotation(annotation) + "\n";
        }

        return annotations;
    }

    private String getAnnotation(Annotation annotation) {
        String annotationSignature = "";

        String annotationSign = "@";

        String annotationName = annotation.annotationType().getSimpleName();

        String annotationArguments = getAnnotationArguments(annotation);

        annotationSignature += annotationSign + annotationName + annotationArguments;

        return annotationSignature;
    }

    private String getAnnotationArguments(Annotation annotation) {
        String annotationArguments = "";

        List<String> arguments = new ArrayList<>();

        for (Map.Entry<String, Object> entry : getAnnotationMemberTypes(annotation).entrySet()) {
            arguments.add(entry.getKey() + " = " + entry.getValue());
        }

        if (!arguments.isEmpty()) {
            annotationArguments += "(" + String.join(", ", arguments) + ")";
        }

        return annotationArguments;
    }

    private Map<String, Object> getAnnotationMemberTypes(Annotation annotation) {
        Map<String, Object> map = new HashMap<String, Object>();

        try {
            Class<? extends Annotation> annotationTypeClass = annotation.annotationType();
            Method[] methods = annotationTypeClass.getDeclaredMethods();

            for (Method method : methods) {
                method.setAccessible(true);

                Object value = method.invoke(annotation);
                String fullValue = value.toString();

                if (value.getClass().isArray()) {
                    List<String> listValue = new ArrayList<String>();
                    for (Object arrayValue : getArrayValues(value)) {
                        if (arrayValue.getClass().isEnum()) {
                            listValue.add(getEnumValue(arrayValue));
                        } else {
                            listValue.add(arrayValue.toString());
                        }
                    }

                    fullValue = "[" + String.join(", ", listValue) + "]";
                }

                if (value.getClass().isEnum()) {
                    fullValue = getEnumValue(value);
                }

                map.put(method.getName(), fullValue);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }

        return map;
    }

    private String getEnumValue(Object object) {
        return object.getClass().getSimpleName() + "." + object;
    }

    private Object[] getArrayValues(Object object) {
        int length = Array.getLength(object);
        Object[] objects = new Object[length];

        for (int i = 0; i < length; i++) {
            objects[i] = (Array.get(object, i));
        }
        return objects;
    }
}

@@ -2146,26 +2146,24 @@
 ble(true);%0D%0A
-%0D%0A
             
@@ -2229,84 +2229,331 @@
     
-String full
+map.put(method.getName(), get
 Value
- = 
+(
 value
-.toString();%0D%0A%0D%0A                if (value.getClass()
+));%0D%0A            %7D%0D%0A        %7D catch (Exception exception) %7B%0D%0A            exception.printStackTrace();%0D%0A        %7D%0D%0A%0D%0A        return map;%0D%0A    %7D%0D%0A%0D%0A    private String getValue(Object object) throws NoSuchMethodException %7B%0D%0A        Class%3C?%3E clazz = object.getClass();%0D%0A        if (clazz
 .isA
@@ -2575,24 +2575,16 @@
         
-       
- 
 List%3CStr
@@ -2634,32 +2634,24 @@
             
-        
 for (Object 
@@ -2682,88 +2682,20 @@
 ues(
-value)) %7B%0D%0A                        if (arrayValue.getClass().isEnum()) %7B%0D%0A      
+object)) %7B%0D%0A
     
@@ -2698,38 +2698,32 @@
                 
-      
 listValue.add(ge
@@ -2723,20 +2723,16 @@
 .add(get
-Enum
 Value(ar
@@ -2760,186 +2760,39 @@
     
-       
-     %7D else %7B%0D%0A                            listValue.add(arrayValue.toString());%0D%0A                        %7D%0D%0A                    %7D%0D%0A%0D%0A                    fullValue = %22%5B%22 +
+%7D%0D%0A%0D%0A            String value =
  Str
@@ -2820,14 +2820,8 @@
 lue)
- + %22%5D%22
 ;%0D%0A 
@@ -2835,134 +2835,102 @@
     
-    %7D%0D%0A%0D%0A                if (value.getClass().isEnum()) %7B%0D%0A                    fullValue = getEnumValue(value);%0D%0A     
+if (listValue.size() == 1) return value;%0D%0A            else return %22%7B%22 + value + %22%7D%22;%0D%0A
         
    %7D
@@ -2917,35 +2917,32 @@
 + %22%7D%22;%0D%0A        
-   
 %7D%0D%0A%0D%0A           
@@ -2942,244 +2942,403 @@
     
-        map.put(method.getName(), fullValue);%0D%0A            %7D%0D%0A        %7D catch (Exception exception) %7B%0D%0A            exception.printStackTrace();%0D%0A        %7D%0D%0A%0D%0A        return map;%0D%0A    %7D%0D%0A%0D%0A    private String getEnumValue(Object 
+if (clazz.isEnum()) return clazz.getSimpleName() + %22.%22 + object;%0D%0A        if (object instanceof String) return %22%5C%22%22 + object + %22%5C%22%22;%0D%0A        if (object instanceof Character) return %22%5C'%22 + object + %22%5C'%22;%0D%0A        if (object instanceof Number %7C%7C object instanceof Boolean) return object.toString();%0D%0A        if (object instanceof Annotation) return getAnnotation(Annotation.class.cast(
 object)
- %7B
+);%0D%0A
 %0D%0A  
@@ -3354,56 +3354,12 @@
 urn 
-object.getClass().getSimpleName() + %22.%22 + object
+null
 ;%0D%0A 

Fix annotation value