package io.asfjava.ui.core.schema;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;

import io.asfjava.ui.core.FormDefinitionGeneratorFactory;
import io.asfjava.ui.core.generators.FormDefinitionGenerator;
import io.asfjava.ui.dto.UiForm;

public final class UiFormSchemaGenerator {

	private static UiFormSchemaGenerator INSTANCE;

	public UiForm generate(Class<? extends Serializable> formDto) throws JsonMappingException {
		ObjectMapper mapper = new ObjectMapper();
		JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper, new CustomSchemaFactoryWrapper());
 		JsonSchema schema = schemaGen.generateSchema(formDto);

		ArrayNode formDefinition = mapper.createArrayNode();

		Arrays.asList(formDto.getDeclaredFields()).stream()
				.forEach(field -> buildFormDefinition(mapper, formDefinition, field));

		return new UiForm(schema, formDefinition);
	}

	private void buildFormDefinition(ObjectMapper mapper, ArrayNode formDefinition, Field field) {
		List<Annotation> annoations = Arrays.asList(field.getAnnotations());
		for (Annotation annotation : annoations) {
			formDefinition.add(buildFieldDefinition(field, annotation, mapper));
		}
	}

	private JsonNode buildFieldDefinition(Field field, Annotation annotation, ObjectMapper mapper) {
		ObjectNode fieldFormDefinition = mapper.createObjectNode();
		FormDefinitionGenerator generator = FormDefinitionGeneratorFactory.getInstance()
				.getGenerator(annotation.annotationType().getName());
		generator.generate(fieldFormDefinition, field);
		return fieldFormDefinition;

	}

	public static UiFormSchemaGenerator get() {
		if (INSTANCE == null) {
			INSTANCE = new UiFormSchemaGenerator();
		}
		return INSTANCE;
	}

	private UiFormSchemaGenerator() {
	}

}

@@ -158,31 +158,8 @@
 ays;
-%0Aimport java.util.List;
 %0A%0Aim
@@ -220,56 +220,8 @@
 on;%0A
-import com.fasterxml.jackson.databind.JsonNode;%0A
 impo
@@ -990,17 +990,16 @@
 per());%0A
- 
 %09%09JsonSc
@@ -1113,22 +1113,22 @@
 %09Arrays.
-asList
+stream
 (formDto
@@ -1152,22 +1152,8 @@
 s())
-.stream()%0A%09%09%09%09
 .for
@@ -1348,16 +1348,17 @@
 finition
+s
 , Field 
@@ -1372,51 +1372,21 @@
 %7B%0A%09%09
-List%3CAnnotation%3E annoations = 
 Arrays.
-asList
+stream
 (fie
@@ -1409,77 +1409,36 @@
 s())
-;
 %0A%09%09
-for (Annotation annotation : annoations) %7B%0A%09%09%09formDefinition.add(
+%09%09.forEach(annotation -%3E 
 buil
@@ -1483,15 +1483,28 @@
 pper
-));%0A%09%09%7D
+, formDefinitions));
 %0A%09%7D%0A
@@ -1517,16 +1517,12 @@
 ate 
-JsonNode
+void
  bui
@@ -1594,16 +1594,46 @@
 r mapper
+,%0A%09%09%09ArrayNode formDefinitions
 ) %7B%0A%09%09Ob
@@ -1831,16 +1831,44 @@
 ame());%0A
+%09%09if (generator != null) %7B%0A%09
 %09%09genera
@@ -1911,23 +1911,37 @@
 eld);%0A%09%09
-return 
+%09formDefinitions.add(
 fieldFor
@@ -1951,18 +1951,22 @@
 finition
+)
 ;%0A
+%09%09%7D
 %0A%09%7D%0A%0A%09pu

work with Stream API instead of iterator or for each