package io.protostuff.generator.html.json.message;

import io.protostuff.compiler.model.Field;
import io.protostuff.compiler.model.FieldModifier;
import io.protostuff.compiler.model.Message;
import io.protostuff.compiler.model.Module;
import io.protostuff.compiler.model.UserTypeContainer;
import io.protostuff.generator.OutputStreamFactory;
import io.protostuff.generator.html.json.AbstractJsonGenerator;
import io.protostuff.generator.html.json.index.NodeType;
import io.protostuff.generator.html.markdown.MarkdownProcessor;

import java.util.stream.Collectors;
import javax.inject.Inject;

/**
 * @author Kostiantyn Shchepanovskyi
 */
public class JsonMessageGenerator extends AbstractJsonGenerator {

    private final MarkdownProcessor markdownProcessor;

    @Inject
    public JsonMessageGenerator(OutputStreamFactory outputStreamFactory, MarkdownProcessor markdownProcessor) {
        super(outputStreamFactory);
        this.markdownProcessor = markdownProcessor;
    }

    @Override
    public void compile(Module module) {
        module.getProtos()
                .forEach(proto -> rec(module, proto));
    }

    private void rec(Module module, UserTypeContainer container) {
        container.getMessages()
                .forEach(message -> {
                    process(module, message);
                    rec(module, message);
                });
    }

    private void process(Module module, Message message) {
        ImmutableMessageDescriptor descriptor = ImmutableMessageDescriptor.builder()
                .type(NodeType.MESSAGE)
                .name(message.getName())
                .canonicalName(message.getCanonicalName())
                .description(markdownProcessor.toHtml(message.getComments()))
                .addAllFields(message.getFields().stream()
                        .map(field -> {
                            ImmutableMessageField.Builder builder = ImmutableMessageField.builder()
                                    .name(field.getName())
                                    .typeId(field.getType().getCanonicalName())
                                    .modifier(getModifier(field))
                                    .tag(field.getTag())
                                    .description(markdownProcessor.toHtml(field.getComments()))
                                    .oneof(field.isOneofPart() ? field.getOneof().getName() : null);
                            boolean isMap = field.isMap();
                            if (isMap) {
                                builder.isMap(true);
                                builder.mapKeyTypeId(getMapKeyType(field));
                                builder.mapValueTypeId(getMapValueType(field));
                            }
                            return builder.build();
                        })
                        .collect(Collectors.toList()))
                .build();
        String output = module.getOutput() + "/data/type/" + message.getCanonicalName() + ".json";
        write(output, descriptor);
    }

    private String getMapKeyType(Field field) {
        Message message = (Message) field.getType();
        Field key = message.getField("key");
        return key.getType().getCanonicalName();
    }

    private String getMapValueType(Field field) {
        Message message = (Message) field.getType();
        Field value = message.getField("value");
        return value.getType().getCanonicalName();
    }

    private MessageFieldModifier getModifier(Field field) {
        FieldModifier modifier = field.getModifier();
        String modifierString = modifier.toString();
        return MessageFieldModifier.fromString(modifierString);
    }
}

@@ -45,16 +45,58 @@
 ssage;%0A%0A
+import io.protostuff.compiler.model.Enum;%0A
 import i
@@ -177,24 +177,71 @@
 ldModifier;%0A
+import io.protostuff.compiler.model.FieldType;%0A
 import io.pr
@@ -2334,52 +2334,36 @@
 ion(
-markdownProcessor.toHtml(field.getComments()
+createFieldDescription(field
 ))%0A 
@@ -3060,16 +3060,16 @@
 .json%22;%0A
-
         
@@ -3094,32 +3094,745 @@
 riptor);%0A    %7D%0A%0A
+    private String createFieldDescription(Field field) %7B%0A        String comments;%0A        if (!field.getComments().isEmpty()) %7B%0A            comments = field.getComments();%0A        %7D else %7B%0A            comments = copyDescriptionFromFieldType(field);%0A        %7D%0A        return markdownProcessor.toHtml(comments);%0A    %7D%0A%0A    private String copyDescriptionFromFieldType(Field field) %7B%0A        String comments;FieldType type = field.getType();%0A        if (type instanceof Message) %7B%0A            comments = ((Message) type).getComments();%0A        %7D else if (type instanceof Enum) %7B%0A            comments = ((Enum) type).getComments();%0A        %7D else %7B%0A            comments = %22%22;%0A        %7D%0A        return comments;%0A    %7D%0A%0A
     private Stri

copy description from message/enum into field if field description is empty