/*
 * 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.hop.metadata.serializer.json;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import org.apache.commons.lang.StringUtils;
import org.apache.hop.core.encryption.ITwoWayPasswordEncoder;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.metadata.api.*;
import org.apache.hop.metadata.util.ReflectionUtil;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.text.SimpleDateFormat;
import java.util.*;

public class JsonMetadataParser<T extends IHopMetadata> {

  private Class<T> managedClass;
  private IHopMetadataProvider metadataProvider;

  public JsonMetadataParser(Class<T> managedClass, IHopMetadataProvider metadataProvider) {
    this.managedClass = managedClass;
    this.metadataProvider = metadataProvider;
  }

  public T loadJsonObject(Class<T> managedClass, JsonParser jsonParser) throws HopException {
    try {
      // Now we can load the annotated fields, the properties:
      //
      T object = managedClass.newInstance();
      loadProperties(object, jsonParser);
      return object;
    } catch (Exception e) {
      throw new HopException("Unable to load JSON object", e);
    }
  }

  private void loadProperties(Object object, com.fasterxml.jackson.core.JsonParser jsonParser)
      throws HopException {
    Class<?> objectClass = object.getClass();
    Map<String, Field> keyFieldMap = new HashMap<>();
    for (Field field : ReflectionUtil.findAllFields(objectClass)) {
      HopMetadataProperty metadataProperty = field.getAnnotation(HopMetadataProperty.class);
      if (metadataProperty != null) {
        String key;
        if (StringUtils.isNotEmpty(metadataProperty.key())) {
          key = metadataProperty.key();
        } else {
          key = field.getName();
        }
        keyFieldMap.put(key, field);

        // We need to go over the boolean fields and consider the defaultBoolean flag.
        // If we don't do this we'll always get the value specified in the constructor.
        //
        Class<?> fieldType = field.getType();
        if (Boolean.class.equals(fieldType) || boolean.class.equals(fieldType)) {
          ReflectionUtil.setFieldValue(
              object, field.getName(), fieldType, metadataProperty.defaultBoolean());
        }
      }
    }

    // Load all the properties found in the JSON...
    //
    try {
      while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
        String key = jsonParser.getCurrentName();
        Field field = keyFieldMap.get(key);
        if (field != null) {
          // This is a recognized piece of data. We can load this...
          //
          loadProperty(object, jsonParser, key, field);
        }
      }
    } catch (Exception e) {
      throw new HopException("Error loading fields for object class " + objectClass.getName(), e);
    }
  }

  private void loadProperty(
      Object object, com.fasterxml.jackson.core.JsonParser jsonParser, String key, Field field)
      throws HopException {
    Class<?> objectClass = object.getClass();
    Class<?> fieldType = field.getType();
    HopMetadataProperty metadataProperty = field.getAnnotation(HopMetadataProperty.class);

    try {
      // Position on the value in the JSON
      //
      jsonParser.nextToken();
      Object fieldValue = null;

      if ("null".equals(jsonParser.getText()) && jsonParser.getValueAsString() == null) {
        // This is the case { "name" : null }
        //
        fieldValue = null;
      } else {
        if (fieldType.isEnum()) {
          final Class<? extends Enum> enumerationClass = (Class<? extends Enum>) field.getType();
          String enumerationName = jsonParser.getText();
          if (StringUtils.isNotEmpty(enumerationName)) {
            fieldValue = Enum.valueOf(enumerationClass, enumerationName);
          }
        } else if (String.class.equals(fieldType)) {
          String string = jsonParser.getText();
          if (metadataProperty.password()) {
            string = metadataProvider.getTwoWayPasswordEncoder().decode(string, true);
          }
          fieldValue = string;
        } else if (int.class.equals(fieldType) || Integer.class.equals(fieldType)) {
          fieldValue = jsonParser.getIntValue();
        } else if (long.class.equals(fieldType) || Long.class.equals(fieldType)) {
          fieldValue = jsonParser.getLongValue();
        } else if (Boolean.class.equals(fieldType) || boolean.class.equals(fieldType)) {
          fieldValue = jsonParser.getBooleanValue();
        } else if (Date.class.equals(fieldType)) {
          String dateString = jsonParser.getText();
          fieldValue = new SimpleDateFormat("yyyy/MM/dd'T'HH:mm:ss").parse(dateString);
        } else if (Map.class.equals(fieldType)) {
          Map<String, String> map = new HashMap<>();
          while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
            String mapKey = jsonParser.getText();
            jsonParser.nextToken();
            String mapValue = jsonParser.getText();
            map.put(mapKey, mapValue);
          }
          fieldValue = map;
        } else if (List.class.equals(fieldType)) {
          ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
          Class<?> listClass = (Class<?>) parameterizedType.getActualTypeArguments()[0];
          if (String.class.equals(listClass)) {
            List<String> list = new ArrayList<>();
            while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
              list.add(jsonParser.getText());
            }
            fieldValue = list;
          } else {
            // List of POJO
            //
            IHopMetadataSerializer<?> serializer = null;
            if (metadataProperty.storeWithName()) {
              if (!IHopMetadata.class.isAssignableFrom(listClass)) {
                throw new HopException(
                    "Error: metadata objects that need to be stored with a name reference need to implement IHopMetadata: "
                        + listClass.getName());
              }
              serializer =
                  metadataProvider.getSerializer((Class<? extends IHopMetadata>) listClass);
            }
            List list = new ArrayList<>();
            while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
              if (metadataProperty.storeWithName()) {
                // Load by name reference
                //
                String name = jsonParser.getText();
                Object listObject = serializer.load(name);
                list.add(listObject);
              } else {
                // Load the object itself
                //
                Object listObject = loadPojoProperties(listClass, jsonParser);
                list.add(listObject);
              }
            }
            fieldValue = list;
          }
        } else {
          // POJO
          //
          if (metadataProperty.storeWithName()) {
            // Load using name reference
            //
            if (!IHopMetadata.class.isAssignableFrom(fieldType)) {
              throw new HopException(
                  "Error: metadata objects that need to be stored with a name reference need to implement IHopMetadata: "
                      + fieldType.getName());
            }
            IHopMetadataSerializer<?> serializer =
                metadataProvider.getSerializer((Class<? extends IHopMetadata>) fieldType);
            String name = jsonParser.getText();
            fieldValue = serializer.load(name);
          } else {
            fieldValue = loadPojoProperties(fieldType, jsonParser);
          }
        }
      }

      // Set the value on the object...
      //
      ReflectionUtil.setFieldValue(object, field.getName(), fieldType, fieldValue);

    } catch (Exception e) {
      throw new HopException(
          "Error loading field with key '"
              + key
              + "' for field '"
              + field.getName()
              + " in class "
              + objectClass.getName(),
          e);
    }
  }

  private Object loadPojoProperties(
      Class<?> fieldType, com.fasterxml.jackson.core.JsonParser jsonParser) throws HopException {
    try {
      Object fieldValue;
      HopMetadataObject hopMetadataObject = fieldType.getAnnotation(HopMetadataObject.class);
      if (hopMetadataObject == null) {
        fieldValue = fieldType.newInstance();
        loadProperties(fieldValue, jsonParser);
      } else {
        jsonParser.nextToken(); // skip {
        String fieldValueId = jsonParser.getText();
        IHopMetadataObjectFactory objectFactory = hopMetadataObject.objectFactory().newInstance();
        fieldValue = objectFactory.createObject(fieldValueId, null); // No parent object
        loadProperties(fieldValue, jsonParser);
        jsonParser.nextToken(); // skip }
      }
      return fieldValue;
    } catch (Exception e) {
      throw new HopException("Error loading POJO field '" + fieldType.getName() + "'", e);
    }
  }

  public JSONObject getJsonObject(T object) throws HopException {
    JSONObject jObject = new JSONObject();
    saveProperties(jObject, object, managedClass);
    return jObject;
  }

  /**
   * Go over all the fields in the object class and see if there are with a HopMetadataProperty
   * annotation...
   *
   * @param jObject
   * @param object
   */
  private void saveProperties(JSONObject jObject, Object object, Class<?> objectClass)
      throws HopException {
    if (object == null) {
      return;
    }
    for (Field objectField : ReflectionUtil.findAllFields(object.getClass())) {
      HopMetadataProperty metadataProperty = objectField.getAnnotation(HopMetadataProperty.class);
      if (metadataProperty != null) {
        // The contents of this field needs to be serialized...
        //
        saveProperty(jObject, object, metadataProperty, objectField);
      }
    }
  }

  private void saveProperty(
      JSONObject jObject, Object object, HopMetadataProperty metadataProperty, Field objectField)
      throws HopException {
    String key = objectField.getName();
    if (StringUtils.isNotEmpty(metadataProperty.key())) {
      key = metadataProperty.key();
    }
    Class<?> fieldType = objectField.getType();
    boolean isBoolean = Boolean.class.equals(fieldType) || boolean.class.equals(fieldType);

    try {
      Object fieldValue = ReflectionUtil.getFieldValue(object, objectField.getName(), isBoolean);
      if (fieldValue == null) {
        jObject.put(key, null);
      } else {
        // Enumeration?
        if (fieldType.isEnum()) {
          // Save the enum as its name
          jObject.put(key, ((Enum) fieldValue).name());
        } else if (String.class.equals(fieldType)) {
          String fieldStringValue = (String) fieldValue;
          if (metadataProperty.password()) {
            ITwoWayPasswordEncoder passwordEncoder = metadataProvider.getTwoWayPasswordEncoder();
            fieldStringValue = passwordEncoder.encode(fieldStringValue, true);
          }
          jObject.put(key, fieldStringValue);
        } else if (int.class.equals(fieldType) || Integer.class.equals(fieldType)) {
          jObject.put(key, fieldValue);
        } else if (long.class.equals(fieldType) || Long.class.equals(fieldType)) {
          jObject.put(key, fieldValue);
        } else if (isBoolean) {
          jObject.put(key, fieldValue);
        } else if (Date.class.equals(fieldType)) {
          String dateString =
              new SimpleDateFormat("yyyy/MM/dd'T'HH:mm:ss").format((Date) fieldValue);
          jObject.put(key, dateString);
        } else if (Map.class.equals(fieldType)) {
          jObject.put(key, new JSONObject((Map) fieldValue));
        } else if (List.class.equals(fieldType)) {
          JSONArray jListObjects = new JSONArray();
          ParameterizedType parameterizedType = (ParameterizedType) objectField.getGenericType();
          Class<?> listClass = (Class<?>) parameterizedType.getActualTypeArguments()[0];

          List<?> fieldListObjects = (List<?>) fieldValue;
          for (Object fieldListObject : fieldListObjects) {
            if (String.class.equals(listClass)) {
              jListObjects.add(fieldListObject);
            } else if (metadataProperty.storeWithName()) {
              String name = ReflectionUtil.getObjectName(fieldListObject);
              jListObjects.add(name);
            } else {
              JSONObject jListObject = savePojoProperty(key, fieldListObject, listClass);
              jListObjects.add(jListObject);
            }
          }
          jObject.put(key, jListObjects);
        } else {
          if (metadataProperty.storeWithName()) {
            // Just save the name
            String name = ReflectionUtil.getObjectName(fieldValue);
            jObject.put(key, name);
          } else {
            JSONObject jPojo = savePojoProperty(key, fieldValue, fieldType);
            jObject.put(key, jPojo);
          }
        }
      }
    } catch (Exception e) {
      throw new HopException(
          "Error serializing field '"
              + objectField.getName()
              + "' with type '"
              + fieldType.toString()
              + "'",
          e);
    }
  }

  private JSONObject savePojoProperty(String key, Object fieldValue, Class<?> fieldType)
      throws HopException {
    try {

      // Check if we can serialize this POJO
      // We're looking for annotation @HopMetadataObject on the POJO class indicating how to
      // instantiate it...
      // If not we assume it's in the current classpath.
      // If we don't find the annotation, we don't serialize
      //
      JSONObject jPojoObject = new JSONObject();

      // We can just serialize this POJO just like any other object with properties...
      //
      saveProperties(jPojoObject, fieldValue, fieldType);

      HopMetadataObject hopMetadataObject = fieldType.getAnnotation(HopMetadataObject.class);
      if (hopMetadataObject == null) {
        return jPojoObject;
      } else {
        IHopMetadataObjectFactory objectFactory = hopMetadataObject.objectFactory().newInstance();
        String fieldValueId = objectFactory.getObjectId(fieldValue);

        // We need to store the object ID (plugin ID, class name, ...)
        // To prevent re-ordering by JSON formatters (or humans) we use the ID as the key for a new
        // JSON block
        // We'll wrap the POJO JSON in that block
        //
        JSONObject jPojoBlock = new JSONObject();

        // The POJO JSON goes into the block
        //
        jPojoBlock.put(fieldValueId, jPojoObject);

        return jPojoBlock;
      }
    } catch (Exception e) {
      throw new HopException(
          "Error saving POJO field with key " + key + ", field type '" + fieldType.getName() + "'",
          e);
    }
  }

  /**
   * Gets provider
   *
   * @return value of provider
   */
  public IHopMetadataProvider getMetadataProvider() {
    return metadataProvider;
  }

  /** @param metadataProvider The provider to set */
  public void setMetadataProvider(IHopMetadataProvider metadataProvider) {
    this.metadataProvider = metadataProvider;
  }
}
