/*
 * Copyright 2018, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.tools.protojs.message;

import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import io.spine.tools.protojs.code.JsGenerator;
import io.spine.tools.protojs.field.FieldHandler;
import io.spine.tools.protojs.field.FieldHandlers;

import java.util.List;

import static io.spine.tools.protojs.types.Types.typeWithProtoPrefix;

// todo add check not null everywhere
public final class MessageHandler {

    public static final String FROM_OBJECT_ARG = "obj";
    public static final String MESSAGE = "message";

    private final Descriptor message;
    private final JsGenerator jsGenerator;

    public MessageHandler(Descriptor message, JsGenerator jsGenerator) {
        this.message = message;
        this.jsGenerator = jsGenerator;
    }

    public void generateJs() {
        generateFromJsonMethod();
        generateFromObjectMethod();
    }

    private void generateFromJsonMethod() {
        jsGenerator.addEmptyLine();
        String typeName = typeWithProtoPrefix(message);
        String functionName = typeName + ".fromJson";
        generateFromJsonCode(typeName, functionName);
    }

    private void generateFromObjectMethod() {
        jsGenerator.addEmptyLine();
        String typeName = typeWithProtoPrefix(message);
        String functionName = typeName + ".fromObject";
        generateFromObjectCode(typeName, functionName);
    }

    private void generateFromJsonCode(String typeName, String functionName) {
        jsGenerator.enterFunction(functionName, "json");
        jsGenerator.addLine("let jsonObject = JSON.parse(json);");
        // todo add return helper to jsGenerator
        jsGenerator.addLine("return " + typeName + ".fromObject(jsonObject);");
        jsGenerator.exitFunction();
    }

    private void generateFromObjectCode(String typeName, String functionName) {
        jsGenerator.enterFunction(functionName, FROM_OBJECT_ARG);
        jsGenerator.addLine("let " + MESSAGE + " = new " + typeName + "();");
        generateFieldsCode();
        jsGenerator.addLine("return " + MESSAGE + ';');
        jsGenerator.exitFunction();
    }

    private void generateFieldsCode() {
        List<FieldDescriptor> fields = message.getFields();
        for (FieldDescriptor field : fields) {
            jsGenerator.addEmptyLine();
            FieldHandler fieldHandler = FieldHandlers.createFor(field, jsGenerator);
            fieldHandler.generateJs();
        }
    }
}

@@ -2119,32 +2119,27 @@
 n%22;%0A        
-generate
+add
 FromJsonCode
@@ -2369,32 +2369,27 @@
 t%22;%0A        
-generate
+add
 FromObjectCo
@@ -2436,32 +2436,27 @@
 rivate void 
-generate
+add
 FromJsonCode
@@ -2805,32 +2805,27 @@
 rivate void 
-generate
+add
 FromObjectCo
@@ -3019,34 +3019,35 @@
         
-generat
+handleMessag
 eFields
-Code
 ();%0A    
@@ -3162,26 +3162,27 @@
 oid 
-generat
+handleMessag
 eFields
-Code
 () %7B

Improve naming