/*******************************************************************************
 * 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.olingo.odata2.jpa.processor.core.access.data;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.olingo.odata2.api.edm.EdmEntitySet;
import org.apache.olingo.odata2.api.edm.EdmEntityType;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
import org.apache.olingo.odata2.api.edm.EdmProperty;
import org.apache.olingo.odata2.api.edm.EdmSimpleType;
import org.apache.olingo.odata2.api.edm.EdmStructuralType;
import org.apache.olingo.odata2.api.edm.EdmTypeKind;
import org.apache.olingo.odata2.api.edm.EdmTyped;
import org.apache.olingo.odata2.api.ep.entry.EntryMetadata;
import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
import org.apache.olingo.odata2.jpa.processor.api.OnJPAWriteContent;
import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
import org.apache.olingo.odata2.jpa.processor.core.model.JPAEdmMappingImpl;

public class JPAEntity {

  private Object jpaEntity = null;
  private JPAEntity parentJPAEntity = null;
  private EdmEntityType oDataEntityType = null;
  private EdmEntitySet oDataEntitySet = null;
  private Class<?> jpaType = null;
  private HashMap<String, Method> accessModifiersWrite = null;
  private JPAEntityParser jpaEntityParser = null;
  private ODataJPAContext oDataJPAContext;
  private OnJPAWriteContent onJPAWriteContent = null;
  private List<String> relatedJPAEntityLink = new ArrayList<String>();
  public HashMap<String, List<Object>> relatedJPAEntityMap = null;
  private EdmNavigationProperty viaNavigationProperty;

  public JPAEntity(final EdmEntityType oDataEntityType, final EdmEntitySet oDataEntitySet,
      final ODataJPAContext context) {
    this.oDataEntityType = oDataEntityType;
    this.oDataEntitySet = oDataEntitySet;
    oDataJPAContext = context;
    try {
      JPAEdmMapping mapping = (JPAEdmMapping) oDataEntityType.getMapping();
      jpaType = mapping.getJPAType();
    } catch (EdmException e) {
      return;
    }
    jpaEntityParser = new JPAEntityParser();
    onJPAWriteContent = oDataJPAContext.getODataContext().getServiceFactory().getCallback(OnJPAWriteContent.class);
  }

  public void setAccessModifersWrite(final HashMap<String, Method> accessModifiersWrite) {
    this.accessModifiersWrite = accessModifiersWrite;
  }

  public void setParentJPAEntity(final JPAEntity jpaEntity) {
    parentJPAEntity = jpaEntity;
  }

  public JPAEntity getParentJPAEntity() {
    return parentJPAEntity;
  }

  public Object getJPAEntity() {
    return jpaEntity;
  }

  public void setViaNavigationProperty(EdmNavigationProperty viaNavigationProperty) {
    this.viaNavigationProperty = viaNavigationProperty;
  }

  public EdmNavigationProperty getViaNavigationProperty() {
    return viaNavigationProperty;
  }

  public void create(final ODataEntry oDataEntry) throws ODataJPARuntimeException {

    if (oDataEntry == null) {
      throw ODataJPARuntimeException
          .throwException(ODataJPARuntimeException.GENERAL, null);
    }
    try {
      EntryMetadata entryMetadata = oDataEntry.getMetadata();
      Map<String, Object> oDataEntryProperties = oDataEntry.getProperties();
      if (oDataEntry.containsInlineEntry()) {
        normalizeInlineEntries(oDataEntryProperties);
      }

      if (oDataEntry.getProperties().size() > 0) {

        write(oDataEntryProperties, true);

        for (String navigationPropertyName : oDataEntityType.getNavigationPropertyNames()) {
          EdmNavigationProperty navProperty =
              (EdmNavigationProperty) oDataEntityType.getProperty(navigationPropertyName);
          if (relatedJPAEntityMap != null && relatedJPAEntityMap.containsKey(navigationPropertyName)) {
            oDataEntry.getProperties().get(navigationPropertyName);
            JPALink.linkJPAEntities(relatedJPAEntityMap.get(navigationPropertyName), jpaEntity,
                navProperty);
            continue;
          }
          // The second condition is required to ensure that there is an explicit request to link
          // two entities. Else the third condition will always be true for cases where two navigations
          // point to same entity types.
          if (parentJPAEntity != null
              && navProperty.getRelationship().equals(getViaNavigationProperty().getRelationship())) {
            List<Object> targetJPAEntities = new ArrayList<Object>();
            targetJPAEntities.add(parentJPAEntity.getJPAEntity());
            JPALink.linkJPAEntities(targetJPAEntities, jpaEntity, navProperty);
          } else if (!entryMetadata.getAssociationUris(navigationPropertyName).isEmpty()) {
            if (!relatedJPAEntityLink.contains(navigationPropertyName)) {
              relatedJPAEntityLink.add(navigationPropertyName);
            }
          }
        }
      }
      if (!relatedJPAEntityLink.isEmpty()) {
        JPALink link = new JPALink(oDataJPAContext);
        link.setSourceJPAEntity(jpaEntity);
        link.create(oDataEntitySet, oDataEntry, relatedJPAEntityLink);
      }
    } catch (EdmException e) {
      throw ODataJPARuntimeException
          .throwException(ODataJPARuntimeException.GENERAL
              .addContent(e.getMessage()), e);
    } catch (ODataJPAModelException e) {
      throw ODataJPARuntimeException
          .throwException(ODataJPARuntimeException.GENERAL
              .addContent(e.getMessage()), e);
    }
  }

  public EdmEntitySet getEdmEntitySet() {
    return oDataEntitySet;
  }

  public void create(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException {
    normalizeInlineEntries(oDataEntryProperties);
    write(oDataEntryProperties, true);
  }

  public void update(final ODataEntry oDataEntry) throws ODataJPARuntimeException {
    if (oDataEntry == null) {
      throw ODataJPARuntimeException
          .throwException(ODataJPARuntimeException.GENERAL, null);
    }
    Map<String, Object> oDataEntryProperties = oDataEntry.getProperties();
    if (oDataEntry.containsInlineEntry()) {
      normalizeInlineEntries(oDataEntryProperties);
    }
    write(oDataEntryProperties, false);
    JPALink link = new JPALink(oDataJPAContext);
    link.setSourceJPAEntity(jpaEntity);
    try {
      link.create(oDataEntitySet, oDataEntry, oDataEntityType.getNavigationPropertyNames());
    } catch (EdmException e) {
      throw ODataJPARuntimeException
          .throwException(ODataJPARuntimeException.GENERAL
              .addContent(e.getMessage()), e);
    } catch (ODataJPAModelException e) {
      throw ODataJPARuntimeException
          .throwException(ODataJPARuntimeException.GENERAL
              .addContent(e.getMessage()), e);
    }
  }

  public void update(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException {
    normalizeInlineEntries(oDataEntryProperties);
    write(oDataEntryProperties, false);
  }

  public void setJPAEntity(final Object jpaEntity) {
    this.jpaEntity = jpaEntity;
  }

  protected void setComplexProperty(Method accessModifier, final Object jpaEntity,
      final EdmStructuralType edmComplexType, final HashMap<String, Object> propertyValue)
      throws EdmException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
      InstantiationException, ODataJPARuntimeException, NoSuchMethodException, SecurityException, SQLException {

    setComplexProperty(accessModifier, jpaEntity, edmComplexType, propertyValue, null);
  }

  protected void setProperty(final Method method, final Object entity, final Object entityPropertyValue,
      final EdmSimpleType type) throws
      IllegalAccessException, IllegalArgumentException, InvocationTargetException, ODataJPARuntimeException {

    setProperty(method, entity, entityPropertyValue, type, null);
  }

  protected void setEmbeddableKeyProperty(final HashMap<String, String> embeddableKeys,
      final List<EdmProperty> oDataEntryKeyProperties,
      final Map<String, Object> oDataEntryProperties, final Object entity)
      throws ODataJPARuntimeException, EdmException, IllegalAccessException, IllegalArgumentException,
      InvocationTargetException, InstantiationException {

    HashMap<String, Object> embeddableObjMap = new HashMap<String, Object>();
    List<EdmProperty> leftODataEntryKeyProperties = new ArrayList<EdmProperty>();
    HashMap<String, String> leftEmbeddableKeys = new HashMap<String, String>();

    for (EdmProperty edmProperty : oDataEntryKeyProperties) {
      if (oDataEntryProperties.containsKey(edmProperty.getName()) == false) {
        continue;
      }

      String edmPropertyName = edmProperty.getName();
      String embeddableKeyNameComposite = embeddableKeys.get(edmPropertyName);
      if (embeddableKeyNameComposite == null) {
        continue;
      }
      String embeddableKeyNameSplit[] = embeddableKeyNameComposite.split("\\.");
      String methodPartName = null;
      Method method = null;
      Object embeddableObj = null;

      if (embeddableObjMap.containsKey(embeddableKeyNameSplit[0]) == false) {
        methodPartName = embeddableKeyNameSplit[0];
        method = jpaEntityParser.getAccessModifierSet(entity, methodPartName);
        embeddableObj = method.getParameterTypes()[0].newInstance();
        method.invoke(entity, embeddableObj);
        embeddableObjMap.put(embeddableKeyNameSplit[0], embeddableObj);
      } else {
        embeddableObj = embeddableObjMap.get(embeddableKeyNameSplit[0]);
      }

      if (embeddableKeyNameSplit.length == 2) {
        methodPartName = embeddableKeyNameSplit[1];
        method = jpaEntityParser.getAccessModifierSet(embeddableObj, methodPartName);
        Object simpleObj = oDataEntryProperties.get(edmProperty.getName());
        method.invoke(embeddableObj, simpleObj);
      } else if (embeddableKeyNameSplit.length > 2) { // Deeply nested
        leftODataEntryKeyProperties.add(edmProperty);
        leftEmbeddableKeys
            .put(edmPropertyName, embeddableKeyNameComposite.split(embeddableKeyNameSplit[0] + ".", 2)[1]);
      }
    }
  }

  protected Object instantiateJPAEntity() throws InstantiationException, IllegalAccessException {
    if (jpaType == null) {
      throw new InstantiationException();
    }

    return jpaType.newInstance();
  }

  private void normalizeInlineEntries(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException {
    List<ODataEntry> entries = null;
    try {
      for (String navigationPropertyName : oDataEntityType.getNavigationPropertyNames()) {
        Object inline = oDataEntryProperties.get(navigationPropertyName);
        if (inline instanceof ODataFeed) {
          entries = ((ODataFeed) inline).getEntries();
        } else if (inline instanceof ODataEntry) {
          entries = new ArrayList<ODataEntry>();
          entries.add((ODataEntry) inline);
        }
        if (entries != null) {
          oDataEntryProperties.put(navigationPropertyName, entries);
          entries = null;
        }
      }
    } catch (EdmException e) {
      throw ODataJPARuntimeException
          .throwException(ODataJPARuntimeException.GENERAL
              .addContent(e.getMessage()), e);
    }
  }

  @SuppressWarnings("unchecked")
  private void write(final Map<String, Object> oDataEntryProperties,
      final boolean isCreate)
      throws ODataJPARuntimeException {
    try {

      EdmStructuralType structuralType = null;
      final List<String> keyNames = oDataEntityType.getKeyPropertyNames();

      if (isCreate) {
        jpaEntity = instantiateJPAEntity();
      } else if (jpaEntity == null) {
        throw ODataJPARuntimeException
            .throwException(ODataJPARuntimeException.RESOURCE_NOT_FOUND, null);
      }

      if (accessModifiersWrite == null) {
        accessModifiersWrite =
            jpaEntityParser.getAccessModifiers(jpaEntity, oDataEntityType, JPAEntityParser.ACCESS_MODIFIER_SET);
      }

      if (oDataEntityType == null || oDataEntryProperties == null) {
        throw ODataJPARuntimeException
            .throwException(ODataJPARuntimeException.GENERAL, null);
      }

      final HashMap<String, String> embeddableKeys =
          jpaEntityParser.getJPAEmbeddableKeyMap(jpaEntity.getClass().getName());
      Set<String> propertyNames = null;
      if (embeddableKeys != null) {
        setEmbeddableKeyProperty(embeddableKeys, oDataEntityType.getKeyProperties(), oDataEntryProperties,
            jpaEntity);

        propertyNames = new HashSet<String>();
        propertyNames.addAll(oDataEntryProperties.keySet());
        for (String key : embeddableKeys.keySet()) {
          propertyNames.remove(key);
        }
      } else {
        propertyNames = oDataEntryProperties.keySet();
      }

      boolean isVirtual = false;
      for (String propertyName : propertyNames) {
        EdmTyped edmTyped = (EdmTyped) oDataEntityType.getProperty(propertyName);
        if (edmTyped instanceof EdmProperty) {
          isVirtual = ((JPAEdmMappingImpl)((EdmProperty) edmTyped).getMapping()).isVirtualAccess();
        } else {
          isVirtual = false;
        }
        Method accessModifier = null;

        switch (edmTyped.getType().getKind()) {
        case SIMPLE:
          if (isCreate == false) {
            if (keyNames.contains(edmTyped.getName())) {
              continue;
            }
          }
          accessModifier = accessModifiersWrite.get(propertyName);
          if (isVirtual) {
            setProperty(accessModifier, jpaEntity, oDataEntryProperties.get(propertyName), (EdmSimpleType) edmTyped
                .getType(), propertyName);
          } else {
            setProperty(accessModifier, jpaEntity, oDataEntryProperties.get(propertyName), (EdmSimpleType) edmTyped
                .getType());
          }
          break;
        case COMPLEX:
          structuralType = (EdmStructuralType) edmTyped.getType();
          accessModifier = accessModifiersWrite.get(propertyName);
          if (isVirtual) {
            setComplexProperty(accessModifier, jpaEntity,
                structuralType,
                (HashMap<String, Object>) oDataEntryProperties.get(propertyName), propertyName);
          } else {
            setComplexProperty(accessModifier, jpaEntity,
                structuralType,
                (HashMap<String, Object>) oDataEntryProperties.get(propertyName));
          }
          break;
        case NAVIGATION:
        case ENTITY:
          if (isCreate) {
            structuralType = (EdmStructuralType) edmTyped.getType();
            EdmNavigationProperty navProperty = (EdmNavigationProperty) edmTyped;
            EdmEntitySet edmRelatedEntitySet = oDataEntitySet.getRelatedEntitySet(navProperty);
            List<ODataEntry> relatedEntries = (List<ODataEntry>) oDataEntryProperties.get(propertyName);
            if (relatedJPAEntityMap == null) {
              relatedJPAEntityMap = new HashMap<String, List<Object>>();
            }
            List<Object> relatedJPAEntities = new ArrayList<Object>();
            for (ODataEntry oDataEntry : relatedEntries) {
              JPAEntity relatedEntity =
                  new JPAEntity((EdmEntityType) structuralType, edmRelatedEntitySet, oDataJPAContext);
              relatedEntity.setParentJPAEntity(this);
              relatedEntity.setViaNavigationProperty(navProperty);
              relatedEntity.create(oDataEntry);
              if (oDataEntry.getProperties().size() == 0) {
                if (!oDataEntry.getMetadata().getUri().isEmpty()
                    && !relatedJPAEntityLink.contains(navProperty.getName())) {
                  relatedJPAEntityLink.add(navProperty.getName());
                }
              } else {
                relatedJPAEntities.add(relatedEntity.getJPAEntity());
              }
            }
            if (!relatedJPAEntities.isEmpty()) {
              relatedJPAEntityMap.put(navProperty.getName(), relatedJPAEntities);
            }
          }
        default:
          continue;
        }
      }
    } catch (Exception e) {
      if (e instanceof ODataJPARuntimeException) {
        throw (ODataJPARuntimeException) e;
      }
      throw ODataJPARuntimeException
          .throwException(ODataJPARuntimeException.GENERAL
              .addContent(e.getMessage()), e);
    }
  }

  @SuppressWarnings("unchecked")
  protected void setComplexProperty(Method accessModifier, final Object jpaEntity,
      final EdmStructuralType edmComplexType, final HashMap<String, Object> propertyValue, String propertyName)
      throws EdmException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
      InstantiationException, ODataJPARuntimeException, NoSuchMethodException, SecurityException, SQLException {

    JPAEdmMapping mapping = (JPAEdmMapping) edmComplexType.getMapping();
    Object embeddableObject = mapping.getJPAType().newInstance();
    if (propertyName != null) {
    	accessModifier.invoke(jpaEntity, propertyName, embeddableObject);
    } else {
    	accessModifier.invoke(jpaEntity, embeddableObject);
    }

    HashMap<String, Method> accessModifiers =
        jpaEntityParser.getAccessModifiers(embeddableObject, edmComplexType,
            JPAEntityParser.ACCESS_MODIFIER_SET);

    for (String edmPropertyName : edmComplexType.getPropertyNames()) {
      EdmTyped edmTyped = (EdmTyped) edmComplexType.getProperty(edmPropertyName);
      accessModifier = accessModifiers.get(edmPropertyName);
      if (edmTyped.getType().getKind().toString().equals(EdmTypeKind.COMPLEX.toString())) {
        EdmStructuralType structualType = (EdmStructuralType) edmTyped.getType();
        if (propertyName != null) {
          setComplexProperty(accessModifier, embeddableObject, structualType,
              (HashMap<String, Object>) propertyValue.get(edmPropertyName), propertyName);
        } else {
          setComplexProperty(accessModifier, embeddableObject, structualType,
              (HashMap<String, Object>) propertyValue.get(edmPropertyName));
        }
      } else {
        if (propertyName != null) {
          setProperty(accessModifier, embeddableObject, propertyValue.get(edmPropertyName),
              (EdmSimpleType) edmTyped.getType(), edmPropertyName);
        } else {
          setProperty(accessModifier, embeddableObject, propertyValue.get(edmPropertyName),
              (EdmSimpleType) edmTyped.getType());
        }
      }
    }
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  protected void setProperty(final Method method, final Object entity, final Object entityPropertyValue,
      final EdmSimpleType type, String propertyName) throws
      IllegalAccessException, IllegalArgumentException, InvocationTargetException, ODataJPARuntimeException {
    if (entityPropertyValue != null) {
      if (propertyName != null) {
        method.invoke(entity, propertyName, entityPropertyValue);
        return;
      }
      Class<?> parameterType = method.getParameterTypes()[0];
      if (type != null && type.getDefaultType().equals(String.class)) {
        if (parameterType.equals(String.class)) {
          method.invoke(entity, entityPropertyValue);
        } else if (parameterType.equals(char[].class)) {
          char[] characters = ((String) entityPropertyValue).toCharArray();
          method.invoke(entity, characters);
        } else if (parameterType.equals(char.class)) {
          char c = ((String) entityPropertyValue).charAt(0);
          method.invoke(entity, c);
        } else if (parameterType.equals(Character[].class)) {
          Character[] characters = JPAEntityParser.toCharacterArray((String) entityPropertyValue);
          method.invoke(entity, (Object) characters);
        } else if (parameterType.equals(Character.class)) {
          Character c = Character.valueOf(((String) entityPropertyValue).charAt(0));
          method.invoke(entity, c);
        } else if (parameterType.isEnum()) {
          Enum e = Enum.valueOf((Class<Enum>) parameterType, (String) entityPropertyValue);
          method.invoke(entity, e);
        }
      } else if (parameterType.equals(Blob.class)) {
        if (onJPAWriteContent == null) {
          throw ODataJPARuntimeException
              .throwException(ODataJPARuntimeException.ERROR_JPA_BLOB_NULL, null);
        } else {
          method.invoke(entity, onJPAWriteContent.getJPABlob((byte[]) entityPropertyValue));
        }
      } else if (parameterType.equals(Clob.class)) {
        if (onJPAWriteContent == null) {
          throw ODataJPARuntimeException
              .throwException(ODataJPARuntimeException.ERROR_JPA_CLOB_NULL, null);
        } else {
          method.invoke(entity, onJPAWriteContent.getJPAClob(((String) entityPropertyValue).toCharArray()));
        }
      } else if (parameterType.equals(Timestamp.class)) {
        Timestamp ts = new Timestamp(((Calendar) entityPropertyValue).getTimeInMillis());
        method.invoke(entity, ts);
      } else if (parameterType.equals(java.util.Date.class)) {
        method.invoke(entity, ((Calendar) entityPropertyValue).getTime());
      } else if (parameterType.equals(java.sql.Date.class)) {
        long timeInMs = ((Calendar) entityPropertyValue).getTimeInMillis();
        method.invoke(entity, new java.sql.Date(timeInMs));
      } else if (parameterType.equals(java.sql.Time.class)) {
        long timeInMs = ((Calendar) entityPropertyValue).getTimeInMillis();
        method.invoke(entity, new java.sql.Time(timeInMs));
      } else {
        method.invoke(entity, entityPropertyValue);
      }
    }
  }
}