/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.flowable.editor.language.json.converter;

import java.util.Map;

import org.flowable.bpmn.model.BaseElement;
import org.flowable.bpmn.model.FieldExtension;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.ServiceTask;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * @author Tijs Rademakers
 * @author Yvo Swillens
 */
public class DecisionTaskJsonConverter extends BaseBpmnJsonConverter {

    protected static final String REFERENCE_TYPE_DECISION_TABLE = "decisionTable";
    protected static final String REFERENCE_TYPE_DECISION_SERVICE = "decisionService";

    public static void fillTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap,
        Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {

        fillJsonTypes(convertersToBpmnMap);
        fillBpmnTypes(convertersToJsonMap);
    }

    public static void fillJsonTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap) {
        convertersToBpmnMap.put(STENCIL_TASK_DECISION, DecisionTaskJsonConverter.class);
    }

    public static void fillBpmnTypes(Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
    }

    @Override
    protected String getStencilId(BaseElement baseElement) {
        return STENCIL_TASK_DECISION;
    }

    @Override
    protected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode, Map<String, JsonNode> shapeMap,
        BpmnJsonConverterContext converterContext) {

        ServiceTask serviceTask = new ServiceTask();
        serviceTask.setType(ServiceTask.DMN_TASK);

        String decisionModelKey = null;
        String referenceType = null;

        JsonNode decisionTableReferenceNode = getProperty(PROPERTY_DECISIONTABLE_REFERENCE, elementNode);
        if (decisionTableReferenceNode != null && decisionTableReferenceNode.has("id") && !decisionTableReferenceNode.get("id").isNull()) {
            String decisionTableId = decisionTableReferenceNode.get("id").asText();
            decisionModelKey = converterContext.getDecisionTableModelKeyForDecisionTableModelId(decisionTableId);
            referenceType = REFERENCE_TYPE_DECISION_TABLE;
        }

        JsonNode decisionServiceReferenceNode = getProperty(PROPERTY_DECISIONSERVICE_REFERENCE, elementNode);
        if (decisionServiceReferenceNode != null && decisionServiceReferenceNode.has("id") && !decisionServiceReferenceNode.get("id").isNull()) {
            String decisionServiceId = decisionServiceReferenceNode.get("id").asText();
            decisionModelKey = converterContext.getDecisionServiceModelKeyForDecisionServiceModelId(decisionServiceId);
            referenceType = REFERENCE_TYPE_DECISION_SERVICE;
        }

        if (decisionModelKey != null) {
            FieldExtension decisionTableKeyField = new FieldExtension();
            decisionTableKeyField.setFieldName(PROPERTY_DECISIONTABLE_REFERENCE_KEY);
            decisionTableKeyField.setStringValue(decisionModelKey);
            serviceTask.getFieldExtensions().add(decisionTableKeyField);
            referenceType = REFERENCE_TYPE_DECISION_SERVICE;
        }

        if (referenceType != null) {
            FieldExtension decisionReferenceType = new FieldExtension();
            decisionReferenceType.setFieldName(PROPERTY_DECISION_REFERENCE_TYPE);
            decisionReferenceType.setStringValue(referenceType);
            serviceTask.getFieldExtensions().add(decisionReferenceType);
        }

        boolean decisionTableThrowErrorOnNoHitsNode = getPropertyValueAsBoolean(PROPERTY_DECISIONTABLE_THROW_ERROR_NO_HITS, elementNode);
        FieldExtension decisionTableThrowErrorOnNoHitsField = new FieldExtension();
        decisionTableThrowErrorOnNoHitsField.setFieldName(PROPERTY_DECISIONTABLE_THROW_ERROR_NO_HITS_KEY);
        decisionTableThrowErrorOnNoHitsField.setStringValue(decisionTableThrowErrorOnNoHitsNode ? "true" : "false");
        serviceTask.getFieldExtensions().add(decisionTableThrowErrorOnNoHitsField);

        boolean fallbackToDefaultTenant = getPropertyValueAsBoolean(PROPERTY_DECISIONTABLE_FALLBACK_TO_DEFAULT_TENANT, elementNode);
        FieldExtension fallbackToDefaultTenantField = new FieldExtension();
        fallbackToDefaultTenantField.setFieldName(PROPERTY_DECISIONTABLE_FALLBACK_TO_DEFAULT_TENANT_KEY);
        fallbackToDefaultTenantField.setStringValue(fallbackToDefaultTenant ? "true" : "false");
        serviceTask.getFieldExtensions().add(fallbackToDefaultTenantField);

        boolean sameDeployment = getPropertyValueAsBoolean(PROPERTY_DECISIONTABLE_SAME_DEPLOYMENT, elementNode);
        FieldExtension sameDeploymentField = new FieldExtension();
        sameDeploymentField.setFieldName(PROPERTY_DECISIONTABLE_SAME_DEPLOYMENT_KEY);
        sameDeploymentField.setStringValue(sameDeployment ? "true" : "false");
        serviceTask.getFieldExtensions().add(sameDeploymentField);

        return serviceTask;
    }

    @Override
    protected void convertElementToJson(ObjectNode propertiesNode, BaseElement baseElement,
        BpmnJsonConverterContext converterContext) {

    }
}

@@ -666,32 +666,81 @@
 el.BaseElement;%0A
+import org.flowable.bpmn.model.ExtensionElement;%0A
 import org.flowa
@@ -770,16 +770,16 @@
 ension;%0A
-
 import o
@@ -2413,16 +2413,147 @@
  null;%0A%0A
+        // when both decision table and decision service reference are present%0A        // decision services reference will prevail%0A
         
@@ -4047,37 +4047,32 @@
 ) %7B%0A            
-Field
 Extension decisi
@@ -4068,42 +4068,39 @@
 sion
- decisionReferenceType
+Element extensionElement
  = new 
-Field
 Exte
@@ -4096,32 +4096,39 @@
  = new Extension
+Element
 ();%0A            
@@ -4131,38 +4131,142 @@
     
-decisionReferenceType.setField
+extensionElement.setNamespace(NAMESPACE);%0A            extensionElement.setNamespacePrefix(%22modeler%22);%0A            extensionElement.set
 Name
@@ -4317,44 +4317,39 @@
     
-decisionReferenceType.setStringValue
+extensionElement.setElementText
 (ref
@@ -4377,39 +4377,34 @@
     serviceTask.
-getFiel
+ad
 dExtensions().ad
@@ -4401,37 +4401,32 @@
 sion
-s().add(decisionReferenceType
+Element(extensionElement
 );%0A 

set decision reference type as extension element (instead of field extension)