/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.wayang.core.util;

import org.apache.commons.lang3.SerializationException;


import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.wayang.core.util.json.JSONArray;
import org.apache.wayang.core.util.json.JSONObject;

/**
 * Utility to deal with {@link JsonSerializable}s.
 */
public class JsonSerializables {

    /**
     * Try to serialize the given {@link Object}. It must be JSON-compatible or a {@link JsonSerializable}.
     *
     * @param obj         the {@link Object} to serialize
     * @param isPolymorph in case a {@link JSONObject} is created, whether it should be tagged with the {@link Class}
     *                    of {@code obj}
     * @return the serialization result
     * @see #isJsonCompatible(Object)
     */
    public static Object serialize(Object obj, boolean isPolymorph) {
        if (obj == null) return null;
        if (isJsonCompatible(obj)) {
            return obj;
        }
        if (obj instanceof JsonSerializable) return serialize((JsonSerializable) obj, isPolymorph);
        throw new IllegalArgumentException(String.format("Cannot serialize %s.", obj));
    }

    /**
     * Serialize the given {@link JsonSerializable}.
     *
     * @param serializable the {@link JsonSerializable} to serialize
     * @param isPolymorph  in case a {@link JSONObject} is created, whether it should be tagged with the {@link Class}
     *                     of {@code serializable}
     * @return the serialization result
     */
    public static JSONObject serialize(JsonSerializable serializable, boolean isPolymorph) {
        return serialize(serializable, isPolymorph, JsonSerializable.uncheckedSerializer);
    }

    /**
     * Serialize the given {@link Object} using a specific {@link JsonSerializer}.
     *
     * @param obj         the {@link Object} to serialize
     * @param isPolymorph in case a {@link JSONObject} is created, whether it should be tagged with the {@link Class}
     *                    of {@code serializable}
     * @param serializer  the {@link JsonSerializer}
     * @return the serialization result
     */
    public static <T> JSONObject serialize(T obj, boolean isPolymorph, JsonSerializer<T> serializer) {
        return addClassTag(obj, serializer.serialize(obj), isPolymorph);
    }

    /**
     * Try to serialize the given {@link Object}s. They must be JSON-compatible or a {@link JsonSerializable}s.
     *
     * @param collection  the {@link Object}s to serialize
     * @param isPolymorph in case a {@link JSONObject} is created, whether it should be tagged with the {@link Class}
     *                    of the according {@link Object}
     * @return the serialization result
     * @see #isJsonCompatible(Object)
     */
    public static JSONArray serializeAll(Collection<?> collection, boolean isPolymorph) {
        if (isJsonNull(collection)) return null;
        JSONArray jsonArray = new JSONArray();
        for (Object obj : collection) {
            jsonArray.put(serialize(obj, isPolymorph));
        }
        return jsonArray;
    }

    /**
     * Serialize the given {@link Object}s using a specific {@link JsonSerializer}.
     *
     * @param collection  the {@link Object}s to serialize
     * @param isPolymorph in case a {@link JSONObject} is created, whether it should be tagged with the {@link Class}
     *                    of {@code serializable}
     * @param serializer  the {@link JsonSerializer}
     * @return the serialization result
     */
    public static <T> JSONArray serializeAll(Collection<T> collection, boolean isPolymorph, JsonSerializer<T> serializer) {
        if (collection == null) return null;
        JSONArray jsonArray = new JSONArray();
        for (T serializable : collection) {
            jsonArray.put(serialize(serializable, isPolymorph, serializer));
        }
        return jsonArray;
    }

    /**
     * Deserialize a given JSON datatype. The following cases are supported:
     * <ul>
     * <li>{@code json} is a (JSON) {@code null} value;</li>
     * <li>{@code json} is a basic (JSON) datatype;</li>
     * <li>{@code json} is a {@link Class}-tagged {@link JSONObject} that corresponds to a {@link JsonSerializable};</li>
     * <li>{@code json} is a {@link JSONArray} with {@link Class}-tagged {@link JSONObject}s that correspond to a
     * {@link JsonSerializable}s - in this case, the result type is a {@link List}.</li>
     * </ul>
     *
     * @param json the JSON data
     * @return the deserialization result
     */
    public static Object deserialize(Object json) {
        if (isJsonNull(json)) return null;
        else if (isUnconvertedInstance(json)) return json;
        else if (json instanceof JSONObject) return deserialize((JSONObject) json);
        else if (json instanceof JSONArray) return deserializeAllAsList((JSONArray) json);

        throw new SerializationException(String.format("Don't know how to deserialize %s.", json));
    }

    /**
     * Deserialize a {@link Class}-tagged {@link JSONObject} that should correspond to a {@link JsonSerializable}.
     *
     * @param jsonObject the {@link JSONObject}
     * @return the deserialization product
     */
    @SuppressWarnings("unchecked")
    public static <T> T deserialize(JSONObject jsonObject) {
        if (isJsonNull(jsonObject)) return null;
        return deserialize(jsonObject, JsonSerializable.uncheckedSerializer());
    }

    /**
     * Deserialize a {@link JSONObject} that should correspond to a {@link JsonSerializable}.
     *
     * @param jsonObject the {@link JSONObject}
     * @param cls        the {@link Class} of the deserialization product
     * @return the deserialization product
     */
    @SuppressWarnings("unchecked")
    public static <T> T deserialize(JSONObject jsonObject, Class<? extends T> cls) {
        if (isJsonNull(jsonObject)) return null;
        return deserialize(jsonObject, (JsonSerializer<T>) JsonSerializable.uncheckedSerializer(), cls);
    }

    /**
     * Deserialize a ({@link Class}-tagged) {@link JSONObject} with a {@link JsonSerializer}.
     *
     * @param jsonObject the {@link JSONObject}
     * @param serializer the {@link JsonSerializer}
     * @return the deserialization product
     */
    public static <T> T deserialize(JSONObject jsonObject, JsonSerializer<T> serializer) {
        if (isJsonNull(jsonObject)) return null;
        return serializer.deserialize(jsonObject);
    }

    /**
     * Deserialize a {@link JSONObject} with a {@link JsonSerializer}.
     *
     * @param jsonObject the {@link JSONObject}
     * @param serializer the {@link JsonSerializer}
     * @param cls        the {@link Class} of the deserialization product
     * @return the deserialization product
     */
    public static <T> T deserialize(JSONObject jsonObject, JsonSerializer<T> serializer, Class<? extends T> cls) {
        if (jsonObject == null || jsonObject.equals(JSONObject.NULL)) return null;
        return serializer.deserialize(jsonObject, cls);
    }

    /**
     * Deserialize a {@link JSONArray} according to the rules of {@link #deserialize(Object)}.
     *
     * @param jsonArray the {@link JSONArray}
     * @return the deserialization product
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> deserializeAllAsList(JSONArray jsonArray) {
        if (isJsonNull(jsonArray)) return null;
        List<T> result = new ArrayList<>(jsonArray.length());
        for (Object jsonElement : jsonArray) {
            result.add((T) deserialize(jsonElement));
        }
        return result;
    }

    /**
     * Deserialize a {@link JSONArray} according to the rules of {@link #deserialize(JSONObject, Class)}.
     *
     * @param jsonArray the {@link JSONArray}
     * @param cls       the {@link Class} of the elements in the {@code jsonArray}
     * @return the deserialization product
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> deserializeAllAsList(JSONArray jsonArray, Class<T> cls) {
        return deserializeAllAsList(jsonArray, (JsonSerializer<T>) JsonSerializable.uncheckedSerializer(), cls);
    }

    /**
     * Deserialize a {@link JSONArray} according to the rules of {@link #deserialize(JSONObject, JsonSerializer)}.
     *
     * @param jsonArray  the {@link JSONArray}
     * @param serializer the {@link JsonSerializer}
     * @return the deserialization product
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> deserializeAllAsList(JSONArray jsonArray, JsonSerializer<T> serializer) {
        List<T> result = new ArrayList<>(jsonArray.length());
        for (Object jsonElement : jsonArray) {
            result.add(isJsonNull(jsonElement) ? null : deserialize((JSONObject) jsonElement, serializer));
        }
        return result;
    }

    /**
     * Deserialize a {@link JSONArray} according to the rules of {@link #deserialize(JSONObject, JsonSerializer, Class)}.
     *
     * @param jsonArray  the {@link JSONArray}
     * @param serializer the {@link JsonSerializer}
     * @param cls        the {@link Class} of the elements in the {@code jsonArray}
     * @return the deserialization product
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> deserializeAllAsList(JSONArray jsonArray, JsonSerializer<T> serializer, Class<T> cls) {
        List<T> result = new ArrayList<>(jsonArray.length());
        for (Object jsonElement : jsonArray) {
            result.add(isJsonNull(jsonElement) ? null : deserialize((JSONObject) jsonElement, serializer, cls));
        }
        return result;
    }

    /**
     * Tag the {@link JSONObject} with the {@link Class} of the other {@link Object}.
     *
     * @param obj        whose {@link Class} should be tagged
     * @param jsonObject that should be tagged
     * @return the {@code jsonObject}
     */

    public static JSONObject addClassTag(Object obj, JSONObject jsonObject) {
        if (isJsonNull(jsonObject)) return jsonObject;
        return jsonObject.put("_class", obj.getClass().getCanonicalName());
    }

    /**
     * Optionally tag the {@link JSONObject} with the {@link Class} of the other {@link Object}.
     *
     * @param obj           whose {@link Class} should be tagged
     * @param jsonObject    that should be tagged
     * @param isAddClassTag if this is {@code false}, no action will be performed
     * @return the {@code jsonObject}
     */
    public static JSONObject addClassTag(Object obj, JSONObject jsonObject, boolean isAddClassTag) {
        return isAddClassTag ? addClassTag(obj, jsonObject) : jsonObject;
    }

    /**
     * Read and load the specified {@link Class} in a {@link JSONObject}.
     *
     * @param jsonObject that contains the {@link Class} tag
     * @return the loaded {@link Class} or {@code null} if none exists
     * @throws ClassNotFoundException if the {@link Class} could not be loaded
     */
    public static Class<?> getClassTag(JSONObject jsonObject) throws ClassNotFoundException {
        if (isJsonNull(jsonObject) || !jsonObject.has("_class")) return null;
        final String className = jsonObject.getString("_class");
        return Class.forName(className);
    }

    /**
     * Tells whether the given instance is a (JSON) {@code null} value.
     *
     * @param obj the instance to test
     * @return whether {@code obj} is a (JSON) {@code null} value
     */
    public static boolean isJsonNull(Object obj) {
        return obj == null || JSONObject.NULL.equals(obj);
    }

    /**
     * Tells whether the given instance is a JSON datatype.
     *
     * @param obj the instance to test
     * @return whether {@code obj} is a JSON datatype
     */
    public static boolean isJsonCompatible(Object obj) {
        return isUnconvertedInstance(obj) || obj == JSONObject.NULL || obj instanceof JSONObject || obj instanceof JSONArray;
    }

    /**
     * Tells whether the given instance does not require conversion, which is the case for {@link Long}s, {@link Integer}s,
     * {@link Double}s, {@link String}s, and {@code null}s.
     *
     * @param obj the instance to test
     * @return whether {@code obj} does not require conversion
     */
    public static boolean isUnconvertedInstance(Object obj) {
        return obj == null || obj instanceof Long || obj instanceof Integer || obj instanceof Double || obj instanceof String;
    }

}
