/*******************************************************************************
 * 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.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import javax.persistence.EntityManager;

import org.apache.olingo.odata2.api.edm.EdmEntitySet;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
import org.apache.olingo.odata2.api.edm.EdmSimpleType;
import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
import org.apache.olingo.odata2.api.exception.ODataException;
import org.apache.olingo.odata2.api.uri.KeyPredicate;
import org.apache.olingo.odata2.api.uri.NavigationSegment;
import org.apache.olingo.odata2.api.uri.UriInfo;
import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPATransaction;
import org.apache.olingo.odata2.jpa.processor.api.access.JPAProcessor;
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.factory.ODataJPAFactory;
import org.apache.olingo.odata2.jpa.processor.core.ODataEntityParser;

public class JPALink {

  private static final String SPACE = " ";
  private static final String ODATA_COMMAND_FILTER = "$filter";
  private static final String ODATA_OPERATOR_OR = "or";
  private static final String ODATA_OPERATOR_NE = "ne";

  private ODataJPAContext context;
  private JPAProcessor jpaProcessor;
  private ODataEntityParser parser;
  private Object targetJPAEntity;
  private Object sourceJPAEntity;

  public JPALink(final ODataJPAContext context) {
    this.context = context;
    jpaProcessor = ODataJPAFactory.createFactory().getJPAAccessFactory().getJPAProcessor(this.context);
    parser = new ODataEntityParser(this.context);
  }

  public void setSourceJPAEntity(final Object jpaEntity) {
    sourceJPAEntity = jpaEntity;
  }

  public void setTargetJPAEntity(final Object jpaEntity) {
    targetJPAEntity = jpaEntity;
  }

  public Object getTargetJPAEntity() {
    return targetJPAEntity;
  }

  public Object getSourceJPAEntity() {
    return sourceJPAEntity;
  }

  public void create(final PostUriInfo uriInfo, final InputStream content, final String requestContentType,
      final String contentType) throws ODataJPARuntimeException, ODataJPAModelException {
    modifyLink((UriInfo) uriInfo, content, requestContentType, contentType);
  }

  public void update(final PutMergePatchUriInfo putUriInfo, final InputStream content, final String requestContentType,
      final String contentType) throws ODataJPARuntimeException, ODataJPAModelException {
    modifyLink((UriInfo) putUriInfo, content, requestContentType, contentType);
  }

  public void delete(final DeleteUriInfo uriInfo) throws ODataJPARuntimeException {
    try {

      int index = context.getODataContext().getPathInfo().getODataSegments().size() - 2;

      List<String> linkSegments = new ArrayList<String>();
      String customLinkSegment = context.getODataContext().getPathInfo().getODataSegments().get(0).getPath();
      linkSegments.add(customLinkSegment);
      customLinkSegment = uriInfo.getNavigationSegments().get(0).getNavigationProperty().getName();
      linkSegments.add(customLinkSegment);

      HashMap<String, String> options = new HashMap<String, String>();
      List<KeyPredicate> keyPredicates = uriInfo.getNavigationSegments().get(0).getKeyPredicates();
      StringBuffer condition = new StringBuffer();
      String literal = null;
      KeyPredicate keyPredicate = null;
      int size = keyPredicates.size();
      for (int i = 0; i < size; i++) {
        keyPredicate = keyPredicates.get(i);

        literal = ((EdmSimpleType) keyPredicate.getProperty().getType()).toUriLiteral(keyPredicate.getLiteral());
        condition.append(keyPredicate.getProperty().getName()).append(SPACE);
        condition.append(ODATA_OPERATOR_NE).append(SPACE);
        condition.append(literal).append(SPACE);
        if (i != size - 1) {
          condition.append(ODATA_OPERATOR_OR).append(SPACE);
        }
      }
      options.put(ODATA_COMMAND_FILTER, condition.toString());

      UriInfo parsedUriInfo = parser.parseLinkSegments(linkSegments, options);
      List<Object> relatedEntities = jpaProcessor.process((GetEntitySetUriInfo) parsedUriInfo);

      parsedUriInfo = parser.parseURISegment(0, index);
      if (parsedUriInfo != null) {
        targetJPAEntity = jpaProcessor.process((GetEntityUriInfo) parsedUriInfo);
        if (targetJPAEntity == null) {
          throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.RESOURCE_X_NOT_FOUND
              .addContent(parsedUriInfo.getTargetEntitySet().getName()), null);
        }
        NavigationSegment navigationSegment = uriInfo.getNavigationSegments().get(0);
        EdmNavigationProperty navigationProperty = navigationSegment.getNavigationProperty();
        delinkJPAEntities(targetJPAEntity, relatedEntities, navigationProperty);
      }

    } catch (EdmException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
    } catch (ODataException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
    }
  }

  public void save() {
    EntityManager em = context.getEntityManager();
    ODataJPATransaction tx = context.getODataJpaTransaction();
    if (!tx.isActive()) {
      tx.begin();
      if (sourceJPAEntity != null) {
        em.persist(sourceJPAEntity);
      }
      if (targetJPAEntity != null) {
        em.persist(targetJPAEntity);
        em.flush();
      }
      tx.commit();
    }

  }

  public void create(final EdmEntitySet entitySet, final ODataEntry oDataEntry,
      final List<String> navigationPropertyNames)
      throws ODataJPARuntimeException,
      ODataJPAModelException {

    List<Object> targetJPAEntities = new ArrayList<Object>();
    try {
      for (String navPropertyName : navigationPropertyNames) {
        List<String> links = oDataEntry.getMetadata().getAssociationUris(navPropertyName);
        if (links == null || links.isEmpty() == true) {
          links = extractLinkURI(oDataEntry, navPropertyName);
        }
        if (links != null && links.isEmpty() == false) {

          EdmNavigationProperty navProperty = (EdmNavigationProperty) entitySet.getEntityType()
              .getProperty(
                  navPropertyName);

          for (String link : links) {
            UriInfo bindingUriInfo = parser.parseBindingLink(link, new HashMap<String, String>());
            targetJPAEntity = jpaProcessor.process((GetEntityUriInfo) bindingUriInfo);
            if (targetJPAEntity != null) {
              targetJPAEntities.add(targetJPAEntity);
            }
          }
          if (!targetJPAEntities.isEmpty()) {
            linkJPAEntities(targetJPAEntities, sourceJPAEntity, navProperty);
          }
          targetJPAEntities.clear();
        }
      }
    } catch (EdmException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
    }

  }

  @SuppressWarnings("unchecked")
  public static void linkJPAEntities(final Collection<Object> targetJPAEntities, final Object sourceJPAEntity,
      final EdmNavigationProperty navigationProperty) throws ODataJPARuntimeException {
    if (targetJPAEntities == null || sourceJPAEntity == null || navigationProperty == null) {
      return;
    }
    try {
      JPAEntityParser entityParser = new JPAEntityParser();
      Method setMethod = entityParser.getAccessModifier(sourceJPAEntity.getClass(),
          navigationProperty, JPAEntityParser.ACCESS_MODIFIER_SET);
      switch (navigationProperty.getMultiplicity()) {
      case MANY:
        Method getMethod = entityParser.getAccessModifier(sourceJPAEntity.getClass(),
            navigationProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
        Collection<Object> relatedEntities = (Collection<Object>) getMethod.invoke(sourceJPAEntity);
        if (relatedEntities == null) {
          throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.ERROR_JPQL_CREATE_REQUEST, null);
        }
        relatedEntities.addAll(targetJPAEntities);
        setMethod.invoke(sourceJPAEntity, relatedEntities);
        break;
      case ONE:
      case ZERO_TO_ONE:
        setMethod.invoke(sourceJPAEntity, targetJPAEntities.iterator().next());
        break;
      }
    } catch (EdmException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
    } catch (IllegalArgumentException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
    } catch (IllegalAccessException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
    } catch (InvocationTargetException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
    }
  }

  @SuppressWarnings("unchecked")
  private List<String> extractLinkURI(ODataEntry oDataEntry, String navigationPropertyName) {

    List<String> links = new ArrayList<String>();

    String link = null;
    Object object = oDataEntry.getProperties().get(navigationPropertyName);
    if (object == null) {
      return links;
    }
    if (object instanceof ODataEntry) {
      link = ((ODataEntry) object).getMetadata().getUri();
      if (!link.isEmpty()) {
        links.add(link);
      }
    } else {
      for (ODataEntry entry : (List<ODataEntry>) object) {
        link = entry.getMetadata().getUri();
        if (link != null && link.isEmpty() == false) {
          links.add(link);
        }
      }
    }

    return links;
  }

  private void modifyLink(final UriInfo uriInfo, final InputStream content, final String requestContentType,
      final String contentType)
      throws ODataJPARuntimeException, ODataJPAModelException {
    try {
      EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
      String targerEntitySetName = targetEntitySet.getName();
      EdmNavigationProperty navigationProperty = null;
      UriInfo getUriInfo = null;

      if (uriInfo.isLinks()) {
        getUriInfo = parser.parseLink(targetEntitySet, content, requestContentType);
        navigationProperty = uriInfo.getNavigationSegments().get(0).getNavigationProperty();
      } else {
        return;
      }

      if (!getUriInfo.getTargetEntitySet().getName().equals(targerEntitySetName))
      {
        throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.RELATIONSHIP_INVALID, null);
      }

      targetJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
      if (targetJPAEntity != null && sourceJPAEntity == null) {
        int index = context.getODataContext().getPathInfo().getODataSegments().size() - 2;
        getUriInfo = parser.parseURISegment(0, index);
        sourceJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
        if (sourceJPAEntity == null) {
          throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.RESOURCE_X_NOT_FOUND
              .addContent(getUriInfo.getTargetEntitySet().getName()), null);
        }
      }
      if (targetJPAEntity != null && sourceJPAEntity != null) {
        List<Object> targetJPAEntities = new ArrayList<Object>();
        targetJPAEntities.add(targetJPAEntity);
        linkJPAEntities(targetJPAEntities, sourceJPAEntity, navigationProperty);
      }

    } catch (IllegalArgumentException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
    } catch (EdmException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
    } catch (ODataException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
    }
  }

  private void delinkJPAEntities(final Object jpaEntity,
      final List<Object> relatedJPAEntities,
      final EdmNavigationProperty targetNavigationProperty)
      throws ODataJPARuntimeException {

    try {
      JPAEntityParser entityParser = new JPAEntityParser();
      Method setMethod = entityParser.getAccessModifier(jpaEntity.getClass(),
          targetNavigationProperty, JPAEntityParser.ACCESS_MODIFIER_SET);

      Method getMethod = entityParser.getAccessModifier(jpaEntity.getClass(),
          targetNavigationProperty, JPAEntityParser.ACCESS_MODIFIER_GET);

      if (getMethod.getReturnType().getTypeParameters() != null
          && getMethod.getReturnType().getTypeParameters().length != 0) {
        setMethod.invoke(jpaEntity, relatedJPAEntities);
      } else {
        setMethod.invoke(jpaEntity, (Object) null);
      }
    } catch (IllegalAccessException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
    } catch (InvocationTargetException e) {
      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
    }

  }
}
