/*
 * Copyright 2018-present Open Networking Foundation
 *
 * 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.onosproject.workflow.api;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.BooleanNode;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.MissingNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Class for injecting json data model on the work-let execution context.
 */
public class JsonDataModelInjector {

    private static final Logger log = LoggerFactory.getLogger(JsonDataModelInjector.class);

    /**
     * Injects data model to work-let.
     * @param worklet work-let to be injected
     * @param context workflow context
     * @throws WorkflowException workflow exception
     */
    public void inject(Worklet worklet, WorkflowContext context) throws WorkflowException {

        handle(worklet, context, this::injectModel);
    }

    /**
     * Inhales data model from work-let.
     * @param worklet work-let to be inhaled
     * @param context workflow context
     * @throws WorkflowException workflow exception
     */
    public void inhale(Worklet worklet, WorkflowContext context) throws WorkflowException {

        handle(worklet, context, this::inhaleModel);
    }

    private void handle(Worklet worklet, WorkflowContext context, DataModelFieldBehavior func)
            throws WorkflowException {
        Class cl = worklet.getClass();
        List<Field> fields = getInheritedFields(cl);
        if (Objects.isNull(fields)) {
            log.error("Invalid fields on {}", cl);
            return;
        }

        for (Field field: fields) {
            Annotation[] annotations = field.getAnnotations();
            if (Objects.isNull(annotations)) {
                continue;
            }
            for (Annotation annotation: annotations) {
                if (!(annotation instanceof JsonDataModel)) {
                    continue;
                }
                JsonDataModel model = (JsonDataModel) annotation;
                func.apply(worklet, context, field, model);
            }
        }
    }

    private static List<Field> getInheritedFields(Class<?> type) {
        List<Field> fields = new ArrayList<Field>();

        Class<?> cl = type;
        while (cl != null && cl != Object.class) {
            for (Field field : cl.getDeclaredFields()) {
                if (!field.isSynthetic()) {
                    fields.add(field);
                }
            }
            cl = cl.getSuperclass();
        }
        return fields;
    }

    /**
     * Functional interface for json data model annotated field behavior.
     */
    @FunctionalInterface
    public interface DataModelFieldBehavior {
        void apply(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
                throws WorkflowException;
    }

    private static Map<Class, DataModelFieldBehavior> injectTypeMap = new HashMap<>();
    static {
        injectTypeMap.put(String.class, JsonDataModelInjector::injectText);
        injectTypeMap.put(Integer.class, JsonDataModelInjector::injectInteger);
        injectTypeMap.put(Boolean.class, JsonDataModelInjector::injectBoolean);
        injectTypeMap.put(JsonNode.class, JsonDataModelInjector::injectJsonNode);
        injectTypeMap.put(ArrayNode.class, JsonDataModelInjector::injectArrayNode);
        injectTypeMap.put(ObjectNode.class, JsonDataModelInjector::injectObjectNode);
    }

    /**
     * Injects data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model data model for the field
     * @throws WorkflowException workflow exception
     */
    private void injectModel(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        DataModelFieldBehavior behavior = injectTypeMap.get(model.type());
        if (Objects.isNull(behavior)) {
            throw new WorkflowException("Not supported type(" + model.type() + ")");
        }
        behavior.apply(worklet, context, field, model);
    }

    /**
     * Injects text data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model text data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void injectText(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        String text = ((JsonDataModelTree) context.data()).textAt(model.path());
        if (Objects.isNull(text)) {
            if (model.optional()) {
                return;
            }
            throw new WorkflowException("Invalid text data model on (" + model.path() + ")");
        }

        if (!(Objects.equals(field.getType(), String.class))) {
            throw new WorkflowException("Target field (" + field + ") is not String");
        }

        try {
            field.setAccessible(true);
            field.set(worklet, text);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }
    }

    /**
     * Injects integer data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model integer data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void injectInteger(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        Integer number = ((JsonDataModelTree) context.data()).intAt(model.path());
        if (Objects.isNull(number)) {
            if (model.optional()) {
                return;
            }
            throw new WorkflowException("Invalid number data model on (" + model.path() + ")");
        }

        if (!(Objects.equals(field.getType(), Integer.class))) {
            throw new WorkflowException("Target field (" + field + ") is not Integer");
        }

        try {
            field.setAccessible(true);
            field.set(worklet, number);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }
    }

    /**
     * Injects boolean data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model boolean data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void injectBoolean(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        Boolean bool = ((JsonDataModelTree) context.data()).booleanAt(model.path());
        if (Objects.isNull(bool)) {
            if (model.optional()) {
                return;
            }
            throw new WorkflowException("Invalid boolean data model on (" + model.path() + ")");
        }

        if (!(Objects.equals(field.getType(), Boolean.class))) {
            throw new WorkflowException("Target field (" + field + ") is not Boolean");
        }

        try {
            field.setAccessible(true);
            field.set(worklet, bool);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }
    }

    /**
     * Injects json node data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model json node data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void injectJsonNode(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        JsonNode jsonNode = ((JsonDataModelTree) context.data()).nodeAt(model.path());
        if (Objects.isNull(jsonNode)) {
            if (model.optional()) {
                return;
            }
            throw new WorkflowException("Invalid json node data model on (" + model.path() + ")");
        }

        if (!(Objects.equals(field.getType(), JsonNode.class))) {
            throw new WorkflowException("Target field (" + field + ") is not JsonNode");
        }

        try {
            field.setAccessible(true);
            field.set(worklet, jsonNode);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }
    }

    /**
     * Injects json array node data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model json array node data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void injectArrayNode(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        ArrayNode arrayNode = ((JsonDataModelTree) context.data()).arrayAt(model.path());
        if (Objects.isNull(arrayNode)) {
            if (model.optional()) {
                return;
            }
            throw new WorkflowException("Invalid array node data model on (" + model.path() + ")");
        }

        if (!(Objects.equals(field.getType(), ArrayNode.class))) {
            throw new WorkflowException("Target field (" + field + ") is not ArrayNode");
        }

        try {
            field.setAccessible(true);
            field.set(worklet, arrayNode);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }
    }

    /**
     * Injects json object node data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model json object node data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void injectObjectNode(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        ObjectNode objNode = ((JsonDataModelTree) context.data()).objectAt(model.path());
        if (Objects.isNull(objNode)) {
            if (model.optional()) {
                return;
            }
            throw new WorkflowException("Invalid object node data model on (" + model.path() + ")");
        }

        if (!(Objects.equals(field.getType(), ObjectNode.class))) {
            throw new WorkflowException("Target field (" + field + ") is not ObjectNode");
        }

        try {
            field.setAccessible(true);
            field.set(worklet, objNode);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }
    }

    private static Map<Class, DataModelFieldBehavior> inhaleTypeMap = new HashMap<>();
    static {
        inhaleTypeMap.put(String.class, JsonDataModelInjector::inhaleText);
        inhaleTypeMap.put(Integer.class, JsonDataModelInjector::inhaleInteger);
        inhaleTypeMap.put(Boolean.class, JsonDataModelInjector::inhaleBoolean);
        inhaleTypeMap.put(JsonNode.class, JsonDataModelInjector::inhaleJsonNode);
        inhaleTypeMap.put(ArrayNode.class, JsonDataModelInjector::inhaleArrayNode);
        inhaleTypeMap.put(ObjectNode.class, JsonDataModelInjector::inhaleObjectNode);
    }

    /**
     * Inhales data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model data model for the field
     * @throws WorkflowException workflow exception
     */
    private void inhaleModel(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        DataModelFieldBehavior behavior = inhaleTypeMap.get(model.type());
        if (Objects.isNull(behavior)) {
            throw new WorkflowException("Not supported type(" + model.type() + ")");
        }
        behavior.apply(worklet, context, field, model);
    }

    /**
     * Inhales text data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model text data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void inhaleText(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        if (!(Objects.equals(field.getType(), String.class))) {
            throw new WorkflowException("Target field (" + field + ") is not String");
        }

        String text;
        try {
            field.setAccessible(true);
            text = (String) field.get(worklet);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }

        if (Objects.isNull(text)) {
            return;
        }

        JsonDataModelTree tree = (JsonDataModelTree) context.data();
        JsonNode jsonNode = tree.nodeAt(model.path());

        if (Objects.isNull(jsonNode) || jsonNode instanceof MissingNode) {
            tree.setAt(model.path(), text);
        } else if (!(jsonNode instanceof TextNode)) {
            throw new WorkflowException("Invalid text data model on (" + model.path() + ")");
        } else {
            tree.remove(model.path());
            tree.setAt(model.path(), text);
        }
    }

    /**
     * Inhales integer data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model integer data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void inhaleInteger(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        if (!(Objects.equals(field.getType(), Integer.class))) {
            throw new WorkflowException("Target field (" + field + ") is not Integer");
        }

        Integer number;
        try {
            field.setAccessible(true);
            number = (Integer) field.get(worklet);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }

        if (Objects.isNull(number)) {
            return;
        }

        JsonDataModelTree tree = (JsonDataModelTree) context.data();
        JsonNode jsonNode = tree.nodeAt(model.path());

        if (Objects.isNull(jsonNode) || jsonNode instanceof MissingNode) {
            tree.setAt(model.path(), number);
        } else if (!(jsonNode instanceof IntNode)) {
            throw new WorkflowException("Invalid integer data model on (" + model.path() + ")");
        } else {
            tree.remove(model.path());
            tree.setAt(model.path(), number);
        }
    }

    /**
     * Inhales boolean data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model boolean data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void inhaleBoolean(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        if (!(Objects.equals(field.getType(), Boolean.class))) {
            throw new WorkflowException("Target field (" + field + ") is not Boolean");
        }

        Boolean bool;
        try {
            field.setAccessible(true);
            bool = (Boolean) field.get(worklet);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }

        if (Objects.isNull(bool)) {
            return;
        }

        JsonDataModelTree tree = (JsonDataModelTree) context.data();
        JsonNode jsonNode = tree.nodeAt(model.path());

        if (Objects.isNull(jsonNode) || jsonNode instanceof MissingNode) {
            tree.setAt(model.path(), bool);
        } else if (!(jsonNode instanceof BooleanNode)) {
            throw new WorkflowException("Invalid boolean data model on (" + model.path() + ")");
        } else {
            tree.remove(model.path());
            tree.setAt(model.path(), bool);
        }
    }

    /**
     * Inhales json node data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model json node data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void inhaleJsonNode(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {

        if (!(Objects.equals(field.getType(), JsonNode.class))) {
            throw new WorkflowException("Target field (" + field + ") is not JsonNode");
        }

        JsonNode tgtJsonNode;
        try {
            field.setAccessible(true);
            tgtJsonNode = (JsonNode) field.get(worklet);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }

        if (Objects.isNull(tgtJsonNode)) {
            return;
        }

        JsonDataModelTree tree = (JsonDataModelTree) context.data();
        JsonNode jsonNode = tree.nodeAt(model.path());

        if (Objects.isNull(jsonNode) || jsonNode instanceof MissingNode) {
            tree.attach(model.path(), new JsonDataModelTree(tgtJsonNode));
        } else if (!(jsonNode instanceof JsonNode)) {
            throw new WorkflowException("Invalid json node data model on (" + model.path() + ")");
        } else {
            // do nothing
        }
    }

    /**
     * Inhales json array node data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model json array node data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void inhaleArrayNode(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {
        if (!(Objects.equals(field.getType(), ArrayNode.class))) {
            throw new WorkflowException("Target field (" + field + ") is not ArrayNode");
        }

        ArrayNode tgtArrayNode;
        try {
            field.setAccessible(true);
            tgtArrayNode = (ArrayNode) field.get(worklet);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }

        if (Objects.isNull(tgtArrayNode)) {
            return;
        }

        JsonDataModelTree tree = (JsonDataModelTree) context.data();
        JsonNode jsonNode = tree.nodeAt(model.path());

        if (Objects.isNull(jsonNode) || jsonNode instanceof MissingNode) {
            tree.attach(model.path(), new JsonDataModelTree(tgtArrayNode));
        } else if (!(jsonNode instanceof ArrayNode)) {
            throw new WorkflowException("Invalid array node data model on (" + model.path() + ")");
        } else {
            // do nothing
        }
    }

    /**
     * Inhales json object node data model on the filed of work-let.
     * @param worklet work-let
     * @param context workflow context
     * @param field the field of work-let
     * @param model json object node data model for the field
     * @throws WorkflowException workflow exception
     */
    private static void inhaleObjectNode(Worklet worklet, WorkflowContext context, Field field, JsonDataModel model)
            throws WorkflowException {
        if (!(Objects.equals(field.getType(), ObjectNode.class))) {
            throw new WorkflowException("Target field (" + field + ") is not ObjectNode");
        }

        ObjectNode tgtObjNode;
        try {
            field.setAccessible(true);
            tgtObjNode = (ObjectNode) field.get(worklet);
        } catch (IllegalAccessException e) {
            throw new WorkflowException(e);
        }

        if (Objects.isNull(tgtObjNode)) {
            return;
        }

        JsonDataModelTree tree = (JsonDataModelTree) context.data();
        JsonNode jsonNode = tree.nodeAt(model.path());

        if (Objects.isNull(jsonNode) || jsonNode instanceof MissingNode) {
            tree.attach(model.path(), new JsonDataModelTree(tgtObjNode));
        } else if (!(jsonNode instanceof ObjectNode)) {
            throw new WorkflowException("Invalid object node data model on (" + model.path() + ")");
        } else {
            // do nothing
        }
    }
}
