/*
 * 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.server.example;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Locale;
import java.util.Random;

import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmSingleton;
import org.apache.olingo.commons.api.ex.ODataNotSupportedException;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataLibraryException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResourceNavigation;
import org.apache.olingo.server.core.ServiceHandler;
import org.apache.olingo.server.core.requests.ActionRequest;
import org.apache.olingo.server.core.requests.DataRequest;
import org.apache.olingo.server.core.requests.FunctionRequest;
import org.apache.olingo.server.core.requests.MediaRequest;
import org.apache.olingo.server.core.requests.MetadataRequest;
import org.apache.olingo.server.core.requests.ServiceDocumentRequest;
import org.apache.olingo.server.core.responses.CountResponse;
import org.apache.olingo.server.core.responses.EntityResponse;
import org.apache.olingo.server.core.responses.EntitySetResponse;
import org.apache.olingo.server.core.responses.ErrorResponse;
import org.apache.olingo.server.core.responses.MetadataResponse;
import org.apache.olingo.server.core.responses.NoContentResponse;
import org.apache.olingo.server.core.responses.PrimitiveValueResponse;
import org.apache.olingo.server.core.responses.PropertyResponse;
import org.apache.olingo.server.core.responses.ServiceDocumentResponse;
import org.apache.olingo.server.core.responses.ServiceResponse;
import org.apache.olingo.server.core.responses.ServiceResponseVisior;
import org.apache.olingo.server.core.responses.StreamResponse;

public class TripPinHandler implements ServiceHandler {
  private OData odata;
  private ServiceMetadata serviceMetadata;
  private final TripPinDataModel dataModel;

  public TripPinHandler(TripPinDataModel datamodel) {
    this.dataModel = datamodel;
  }

  @Override
  public void init(OData odata, ServiceMetadata serviceMetadata) {
    this.odata = odata;
    this.serviceMetadata = serviceMetadata;
  }

  @Override
  public void readMetadata(MetadataRequest request, MetadataResponse response)
      throws ODataLibraryException, ODataApplicationException {
    response.writeMetadata();
  }

  @Override
  public void readServiceDocument(ServiceDocumentRequest request, ServiceDocumentResponse response)
      throws ODataLibraryException, ODataApplicationException {
    response.writeServiceDocument(request.getODataRequest().getRawBaseUri());
  }

  static class EntityDetails {
    EntityCollection entitySet = null;
    Entity entity = null;
    EdmEntityType entityType;
    String navigationProperty;
    Entity parentEntity = null;
  }

  private EntityDetails process(final DataRequest request) throws ODataApplicationException {
    EntityCollection entitySet = null;
    Entity entity = null;
    EdmEntityType entityType;
    Entity parentEntity = null;

    if (request.isSingleton()) {
      EdmSingleton singleton = request.getUriResourceSingleton().getSingleton();
      entityType = singleton.getEntityType();
      if (singleton.getName().equals("Me")) {
        entitySet = this.dataModel.getEntitySet("People");
        entity = entitySet.getEntities().get(0);
      }
    } else {
      final EdmEntitySet edmEntitySet = request.getEntitySet();
      entityType = edmEntitySet.getEntityType();
      List<UriParameter> keys = request.getKeyPredicates();

      // TODO: This example so far ignores all system options; but a real
      // service should not
      if (keys != null && !keys.isEmpty()) {
        entity = this.dataModel.getEntity(edmEntitySet.getName(), keys);
      } else {
        int skip = 0;
        if (request.getUriInfo().getSkipTokenOption() != null) {
          skip = Integer.parseInt(request.getUriInfo().getSkipTokenOption().getValue());
        }
        int pageSize = getPageSize(request);
        entitySet = this.dataModel.getEntitySet(edmEntitySet.getName(), skip, pageSize);
        if (entitySet.getEntities().size() == pageSize) {
          try {
            entitySet.setNext(new URI(request.getODataRequest().getRawRequestUri() + "?$skiptoken="
                + (skip + pageSize)));
          } catch (URISyntaxException e) {
            throw new ODataApplicationException(e.getMessage(), 500, Locale.getDefault());
          }
        }
      }
    }
    EntityDetails details = new EntityDetails();

    if (!request.getNavigations().isEmpty() && entity != null) {
      UriResourceNavigation lastNavigation = request.getNavigations().getLast();
      for (UriResourceNavigation nav : request.getNavigations()) {
        entityType = nav.getProperty().getType();
        if (nav.isCollection()) {
          entitySet = this.dataModel.getNavigableEntitySet(entity, nav);
        } else {
          parentEntity = entity;
          entity = this.dataModel.getNavigableEntity(parentEntity, nav);
        }
      }
      details.navigationProperty = lastNavigation.getProperty().getName();
    }

    details.entity = entity;
    details.entitySet = entitySet;
    details.entityType = entityType;
    details.parentEntity = parentEntity;
    return details;
  }

  @Override
  public <T extends ServiceResponse> void read(final DataRequest request, final T response)
      throws ODataLibraryException, ODataApplicationException {

    final EntityDetails details = process(request);

    response.accepts(new ServiceResponseVisior() {
      @Override
      public void visit(CountResponse response) throws ODataLibraryException, ODataApplicationException {
        response.writeCount(details.entitySet.getCount());
      }

      @Override
      public void visit(PrimitiveValueResponse response) throws ODataLibraryException,
          ODataApplicationException {
        EdmProperty edmProperty = request.getUriResourceProperty().getProperty();
        Property property = details.entity.getProperty(edmProperty.getName());
        response.write(property.getValue());
      }

      @Override
      public void visit(PropertyResponse response) throws ODataLibraryException,
          ODataApplicationException {
        EdmProperty edmProperty = request.getUriResourceProperty().getProperty();
        Property property = details.entity.getProperty(edmProperty.getName());
        response.writeProperty(edmProperty.getType(), property);
      }

      @Override
      public void visit(StreamResponse response) throws ODataLibraryException,
          ODataApplicationException {
        // stream property response
        response.writeStreamResponse(new ByteArrayInputStream("dummy".getBytes()),
            ContentType.APPLICATION_OCTET_STREAM);
      }

      @Override
      public void visit(EntitySetResponse response) throws ODataLibraryException,
          ODataApplicationException {
        if (request.getPreference("odata.maxpagesize") != null) {
          response.writeHeader("Preference-Applied", "odata.maxpagesize="+request.getPreference("odata.maxpagesize"));
        }
        if (details.entity == null && !request.getNavigations().isEmpty()) {
          response.writeReadEntitySet(details.entityType, new EntityCollection());
        } else {
          response.writeReadEntitySet(details.entityType, details.entitySet);
        }
      }

      @Override
      public void visit(EntityResponse response) throws ODataLibraryException,
          ODataApplicationException {
        if (details.entity == null && !request.getNavigations().isEmpty()) {
          response.writeNoContent(true);
        } else {
          response.writeReadEntity(details.entityType, details.entity);
        }
      }
    });
  }

  private int getPageSize(DataRequest request) {
    String size = request.getPreference("odata.maxpagesize");
    if (size == null) {
      return 8;
    }
    return Integer.parseInt(size);
  }

  @Override
  public void createEntity(DataRequest request, Entity entity, EntityResponse response)
      throws ODataLibraryException, ODataApplicationException {
    EdmEntitySet edmEntitySet = request.getEntitySet();

    Entity created = this.dataModel.createEntity(edmEntitySet, entity, request.getODataRequest().getRawBaseUri());

    try {
      // create references, they come in "@odata.bind" value
      List<Link> bindings = entity.getNavigationBindings();
      if (bindings != null & !bindings.isEmpty()) {
        for (Link link : bindings) {
          String navigationProperty = link.getTitle();
          String uri = link.getBindingLink();
          if (uri != null) {
            DataRequest bindingRequest = request.parseLink(new URI(uri));

            Entity reference = this.dataModel.getEntity(bindingRequest.getEntitySet().getName(),
                bindingRequest.getKeyPredicates());

            this.dataModel.addNavigationLink(navigationProperty, created, reference);

          } else {
            for (String binding : link.getBindingLinks()) {
              DataRequest bindingRequest = request.parseLink(new URI(binding));

              Entity reference = this.dataModel.getEntity(bindingRequest.getEntitySet().getName(),
                  bindingRequest.getKeyPredicates());

              this.dataModel.addNavigationLink(navigationProperty, created, reference);
            }
          }
        }
      }
    } catch (URISyntaxException e) {
      throw new ODataApplicationException(e.getMessage(), 500, Locale.getDefault());
    }

    response.writeCreatedEntity(edmEntitySet, created);
  }

  @Override
  public void updateEntity(DataRequest request, Entity entity, boolean merge, String eTag,
      EntityResponse response) throws ODataLibraryException, ODataApplicationException {
    EdmEntitySet edmEntitySet = request.getEntitySet();
    
    Entity currentEntity = this.dataModel.getEntity(edmEntitySet.getName(), request.getKeyPredicates());
    if (currentEntity == null) {
      response.writeNotFound(true);
      return;
    }
    String key = edmEntitySet.getEntityType().getKeyPredicateNames().get(0);
    String baseURL = request.getODataRequest().getRawBaseUri();
    boolean updated = this.dataModel.updateEntity(edmEntitySet, eTag, key, currentEntity
        .getProperty(key).getValue(), merge, entity, baseURL);

    if (updated) {
      response.writeUpdatedEntity();
    } else {
      response.writeNotModified();
    }
  }

  @Override
  public void deleteEntity(DataRequest request, String eTag, EntityResponse response)
      throws ODataLibraryException, ODataApplicationException {

    EdmEntitySet edmEntitySet = request.getEntitySet();
    Entity entity = this.dataModel.getEntity(edmEntitySet.getName(), request.getKeyPredicates());
    if (entity == null) {
      response.writeNotFound(true);
      return;
    }
    String key = edmEntitySet.getEntityType().getKeyPredicateNames().get(0);
    boolean removed = this.dataModel.deleteEntity(edmEntitySet.getName(), eTag, key, entity
        .getProperty(key).getValue());

    if (removed) {
      response.writeDeletedEntityOrReference();
    } else {
      response.writeNotFound(true);
    }
  }

  @Override
  public void updateProperty(DataRequest request, final Property property, boolean rawValue, boolean merge,
      String entityETag, PropertyResponse response) throws ODataLibraryException,
      ODataApplicationException {

    if (rawValue && property.getValue() != null) {
      // this is more generic, stricter conversion rules must taken in a real service
      byte[] value = (byte[])property.getValue();
      property.setValue(ValueType.PRIMITIVE, new String(value));
    }
    
    EdmEntitySet edmEntitySet = request.getEntitySet();
    Entity entity = this.dataModel.getEntity(edmEntitySet.getName(), request.getKeyPredicates());
    if (entity == null) {
      response.writeNotFound(true);
      return;
    }

    String key = edmEntitySet.getEntityType().getKeyPredicateNames().get(0);
    boolean replaced = this.dataModel.updateProperty(edmEntitySet.getName(), entityETag, key,
        entity.getProperty(key).getValue(), property);

    if (replaced) {
      if (property.getValue() == null) {
        response.writePropertyDeleted();
      } else {
        response.writePropertyUpdated();
      }
    } else {
      response.writeServerError(true);
    }
  }

  @Override
  public <T extends ServiceResponse> void invoke(FunctionRequest request, HttpMethod method,
      T response) throws ODataLibraryException, ODataApplicationException {
    EdmFunction function = request.getFunction();
    if (function.getName().equals("GetNearestAirport")) {

      final EdmEntityType type = serviceMetadata.getEdm().getEntityContainer(null)
          .getEntitySet("Airports").getEntityType();

      EntityCollection es = this.dataModel.getEntitySet("Airports");
      int i = new Random().nextInt(es.getEntities().size());
      final Entity entity = es.getEntities().get(i);

      response.accepts(new ServiceResponseVisior() {
        @Override
        public void visit(EntityResponse response) throws ODataLibraryException,
            ODataApplicationException {
          response.writeReadEntity(type, entity);
        }
      });
    }
  }

  @Override
  public <T extends ServiceResponse> void invoke(ActionRequest request, String eTag, T response)
      throws ODataLibraryException, ODataApplicationException {
    EdmAction action = request.getAction();
    if (action.getName().equals("ResetDataSource")) {
      try {
        this.dataModel.loadData();
        response.accepts(new ServiceResponseVisior() {
          @Override
          public void visit(NoContentResponse response) throws ODataLibraryException,
              ODataApplicationException {
            response.writeNoContent();
          }
        });
      } catch (Exception e) {
        response.writeServerError(true);
      }
    } else {
      response.writeServerError(true);
    }
  }

  @Override
  public void readMediaStream(MediaRequest request, StreamResponse response)
      throws ODataLibraryException, ODataApplicationException {

    final EdmEntitySet edmEntitySet = request.getEntitySet();
    List<UriParameter> keys = request.getKeyPredicates();
    Entity entity = this.dataModel.getEntity(edmEntitySet.getName(), keys);

    InputStream contents = this.dataModel.readMedia(entity);
    response.writeStreamResponse(contents, request.getResponseContentType());
  }

  @Override
  public void upsertMediaStream(MediaRequest request, String entityETag, InputStream mediaContent,
      NoContentResponse response) throws ODataLibraryException, ODataApplicationException {
    final EdmEntitySet edmEntitySet = request.getEntitySet();
    List<UriParameter> keys = request.getKeyPredicates();
    Entity entity = this.dataModel.getEntity(edmEntitySet.getName(), keys);

    if (mediaContent == null) {
      boolean deleted = this.dataModel.deleteMedia(entity);
      if (deleted) {
        response.writeNoContent();
      } else {
        response.writeNotFound();
      }
    } else {
      boolean updated = this.dataModel.updateMedia(entity, mediaContent);
      if (updated) {
        response.writeNoContent();
      } else {
        response.writeServerError(true);
      }
    }
  }

  @Override
  public void upsertStreamProperty(DataRequest request, String entityETag, InputStream streamContent,
      NoContentResponse response) throws ODataLibraryException, ODataApplicationException {
    final EdmEntitySet edmEntitySet = request.getEntitySet();
    List<UriParameter> keys = request.getKeyPredicates();
    Entity entity = this.dataModel.getEntity(edmEntitySet.getName(), keys);

    EdmProperty property = request.getUriResourceProperty().getProperty();

    if (streamContent == null) {
      boolean deleted = this.dataModel.deleteStream(entity, property);
      if (deleted) {
        response.writeNoContent();
      } else {
        response.writeNotFound();
      }
    } else {
      boolean updated = this.dataModel.updateStream(entity, property, streamContent);
      if (updated) {
        response.writeNoContent();
      } else {
        response.writeServerError(true);
      }
    }
  }

  @Override
  public void addReference(DataRequest request, String entityETag, URI referenceId,
      NoContentResponse response) throws ODataLibraryException, ODataApplicationException {

    final EntityDetails details = process(request);

    DataRequest bindingRequest = request.parseLink(referenceId);
    Entity linkEntity = this.dataModel.getEntity(bindingRequest.getEntitySet().getName(),
        bindingRequest.getKeyPredicates());
    this.dataModel.addNavigationLink(details.navigationProperty, details.entity, linkEntity);
    response.writeNoContent();
  }

  @Override
  public void updateReference(DataRequest request, String entityETag, URI updateId,
      NoContentResponse response) throws ODataLibraryException, ODataApplicationException {
    // this single valued navigation.
    boolean updated = false;
    final EntityDetails details = process(request);
    DataRequest updateRequest = request.parseLink(updateId);
    Entity updateEntity = this.dataModel.getEntity(updateRequest.getEntitySet().getName(),
        updateRequest.getKeyPredicates());
    if (updateEntity != null) {
      updated = this.dataModel.updateNavigationLink(details.navigationProperty,
        details.parentEntity, updateEntity);
    }

    if (updated) {
      response.writeNoContent();
    } else {
      response.writeServerError(true);
    }
  }

  @Override
  public void deleteReference(DataRequest request, URI deleteId, String entityETag,
      NoContentResponse response) throws ODataLibraryException, ODataApplicationException {
    boolean removed = false;
    if (deleteId != null) {
      final EntityDetails details = process(request);
      DataRequest deleteRequest = request.parseLink(deleteId);
      Entity deleteEntity = this.dataModel.getEntity(deleteRequest.getEntitySet().getName(),
          deleteRequest.getKeyPredicates());
      if (deleteEntity != null) {
        removed = this.dataModel.removeNavigationLink(details.navigationProperty, details.entity,
            deleteEntity);
      }
    } else {
      // this single valued navigation.
      final EntityDetails details = process(request);
      removed = this.dataModel.removeNavigationLink(details.navigationProperty,
          details.parentEntity, details.entity);
    }
    if (removed) {
      response.writeNoContent();
    } else {
      response.writeServerError(true);
    }
  }

  @Override
  public void anyUnsupported(ODataRequest request, ODataResponse response)
      throws ODataLibraryException, ODataApplicationException {
    response.setStatusCode(500);
  }

  @Override
  public String startTransaction() {
    return null;
  }

  @Override
  public void commit(String txnId) {
  }

  @Override
  public void rollback(String txnId) {
  }

  @Override
  public void crossJoin(DataRequest dataRequest, List<String> entitySetNames, ODataResponse response) {
    response.setStatusCode(501);
  }
  
  @Override
  public void apply(DataRequest dataRequest, ODataResponse response)
      throws ODataLibraryException, ODataApplicationException {
    response.setStatusCode(501);
  }

  @Override
  public void upsertEntity(DataRequest request, Entity entity, boolean merge, String entityETag, 
      EntityResponse response) throws ODataLibraryException, ODataApplicationException {
    EdmEntitySet edmEntitySet = request.getEntitySet();
    Entity currentEntity = this.dataModel.getEntity(edmEntitySet.getName(), request.getKeyPredicates());
    if(currentEntity == null) {
      createEntity(request, entity, response);
    } else {
      updateEntity(request, entity, merge, entityETag, response);
    }
  }

  @Override
  public boolean supportsDataIsolation() {
    return false;
  }
  
  @Override
  public void processError(ODataServerError error, ErrorResponse response) {
    error.getException().printStackTrace();
    response.writeError(error);
  }
}
