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

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URI;
import java.util.List;

import org.apache.olingo.commons.api.Constants;
import org.apache.olingo.commons.api.IConstants;
import org.apache.olingo.commons.api.constants.Constantsv00;
import org.apache.olingo.commons.api.data.AbstractEntityCollection;
import org.apache.olingo.commons.api.data.AbstractODataObject;
import org.apache.olingo.commons.api.data.Annotatable;
import org.apache.olingo.commons.api.data.Annotation;
import org.apache.olingo.commons.api.data.ComplexValue;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.data.Linked;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.Valuable;
import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.edm.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.core.edm.EdmTypeInfo;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.serializer.EdmAssistedSerializer;
import org.apache.olingo.server.api.serializer.EdmAssistedSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.serializer.SerializerException.MessageKeys;
import org.apache.olingo.server.api.serializer.SerializerResult;
import org.apache.olingo.server.core.serializer.SerializerResultImpl;
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
import org.apache.olingo.server.core.serializer.utils.ContentTypeHelper;
import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;

public class EdmAssistedJsonSerializer implements EdmAssistedSerializer {

  private static final String IO_EXCEPTION_TEXT = "An I/O exception occurred.";

  protected final boolean isIEEE754Compatible;
  protected final boolean isODataMetadataNone;
  protected final boolean isODataMetadataFull;
  private IConstants constants;

  public EdmAssistedJsonSerializer(final ContentType contentType) {
    this.isIEEE754Compatible = ContentTypeHelper.isODataIEEE754Compatible(contentType);
    this.isODataMetadataNone = ContentTypeHelper.isODataMetadataNone(contentType);
    this.isODataMetadataFull = ContentTypeHelper.isODataMetadataFull(contentType);
    this.constants = new Constantsv00();
  }
  
  public EdmAssistedJsonSerializer(final ContentType contentType, final IConstants constants) {
    this.isIEEE754Compatible = ContentTypeHelper.isODataIEEE754Compatible(contentType);
    this.isODataMetadataNone = ContentTypeHelper.isODataMetadataNone(contentType);
    this.isODataMetadataFull = ContentTypeHelper.isODataMetadataFull(contentType);
    this.constants = constants;
  }

  @Override
  public SerializerResult entityCollection(final ServiceMetadata metadata, final EdmEntityType entityType,
      final AbstractEntityCollection entityCollection, final EdmAssistedSerializerOptions options)
      throws SerializerException {
    return serialize(metadata, entityType, entityCollection, options == null ? null : options.getContextURL());
  }

  public SerializerResult entity(final ServiceMetadata metadata, final EdmEntityType entityType, final Entity entity,
      final EdmAssistedSerializerOptions options) throws SerializerException {
    return serialize(metadata, entityType, entity, options == null ? null : options.getContextURL());
  }

  protected SerializerResult serialize(final ServiceMetadata metadata, final EdmEntityType entityType,
      final AbstractODataObject obj, final ContextURL contextURL) throws SerializerException {
    final String metadataETag =
        isODataMetadataNone || metadata == null || metadata.getServiceMetadataETagSupport() == null ? null : metadata
            .getServiceMetadataETagSupport().getMetadataETag();
    final String contextURLString = isODataMetadataNone || contextURL == null ? null : ContextURLBuilder.create(
        contextURL).toASCIIString();
    OutputStream outputStream = null;
    SerializerException cachedException = null;
    
    CircleStreamBuffer buffer = new CircleStreamBuffer();
    outputStream = buffer.getOutputStream();
    try (JsonGenerator json = new JsonFactory().createGenerator(outputStream)) {
      if (obj instanceof AbstractEntityCollection) {
        doSerialize(entityType, (AbstractEntityCollection) obj, contextURLString, metadataETag, json);
      } else if (obj instanceof Entity) {
        doSerialize(entityType, (Entity) obj, contextURLString, metadataETag, json);
      } else {
        throw new SerializerException("Input type not supported.", MessageKeys.NOT_IMPLEMENTED);
      }
      json.flush();
      json.close();
      return SerializerResultImpl.with().content(buffer.getInputStream()).build();
    } catch (final IOException e) {
      cachedException = new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION);
      throw cachedException;
    } finally {
      if (outputStream != null) {
        try {
          outputStream.close();
        } catch (final IOException e) {
          throw cachedException == null ? new SerializerException(IO_EXCEPTION_TEXT, e,
              SerializerException.MessageKeys.IO_EXCEPTION) : cachedException;
        }
      }
    }
  }

  protected void doSerialize(final EdmEntityType entityType, final AbstractEntityCollection entityCollection,
      final String contextURLString, final String metadataETag, JsonGenerator json)
      throws IOException, SerializerException {

    json.writeStartObject();

    metadata(contextURLString, metadataETag, null, null, entityCollection.getId(), false, json);

    if (entityCollection.getCount() != null) {
      if (isIEEE754Compatible) {
        json.writeStringField(constants.getCount(), Integer.toString(entityCollection.getCount()));
      } else {
        json.writeNumberField(constants.getCount(), entityCollection.getCount());
      }
    }
    if (entityCollection.getDeltaLink() != null) {
      json.writeStringField(constants.getDeltaLink(), entityCollection.getDeltaLink().toASCIIString());
    }

    for (final Annotation annotation : entityCollection.getAnnotations()) {
      valuable(json, annotation, '@' + annotation.getTerm(), null, null);
    }

    json.writeArrayFieldStart(Constants.VALUE);
    for (final Entity entity : entityCollection) {
      doSerialize(entityType, entity, null, null, json);
    }
    json.writeEndArray();

    if (entityCollection.getNext() != null) {
      json.writeStringField(constants.getNextLink(), entityCollection.getNext().toASCIIString());
    }

    json.writeEndObject();
  }

  protected void doSerialize(final EdmEntityType entityType, final Entity entity,
      final String contextURLString, final String metadataETag, JsonGenerator json)
      throws IOException, SerializerException {

    json.writeStartObject();

    final String typeName = entity.getType() == null ? null : new EdmTypeInfo.Builder().setTypeExpression(entity
        .getType()).build().external();
    metadata(contextURLString, metadataETag, entity.getETag(), typeName, entity.getId(), true, json);

    for (final Annotation annotation : entity.getAnnotations()) {
      valuable(json, annotation, '@' + annotation.getTerm(), null, null);
    }

    for (final Property property : entity.getProperties()) {
      final String name = property.getName();
      final EdmProperty edmProperty = entityType == null || entityType.getStructuralProperty(name) == null ? null
          : entityType.getStructuralProperty(name);
      valuable(json, property, name, edmProperty == null ? null : edmProperty.getType(), edmProperty);
    }

    if (!isODataMetadataNone &&
        entity.getEditLink() != null && entity.getEditLink().getHref() != null) {
      json.writeStringField(constants.getEditLink(), entity.getEditLink().getHref());

      if (entity.isMediaEntity()) {
        json.writeStringField(constants.getMediaReadLink(), entity.getEditLink().getHref() + "/$value");
      }
    }

    links(entity, entityType, json);

    json.writeEndObject();
  }

  private void metadata(final String contextURLString, final String metadataETag, final String eTag,
      final String type, final URI id, final boolean writeNullId, JsonGenerator json)
      throws IOException, SerializerException {
    if (!isODataMetadataNone) {
      if (contextURLString != null) {
        json.writeStringField(constants.getContext(), contextURLString);
      }
      if (metadataETag != null) {
        json.writeStringField(constants.getMetadataEtag(), metadataETag);
      }
      if (eTag != null) {
        json.writeStringField(constants.getEtag(), eTag);
      }
      if(isODataMetadataFull){
        if (type != null) {
          json.writeStringField(constants.getType(), type);
        }
        if (id == null) {
          if (writeNullId) {
            json.writeNullField(constants.getId());
          }
        } else {
          json.writeStringField(constants.getId(), id.toASCIIString());
        }
      }
    }
  }

  private void links(final Linked linked, final EdmEntityType entityType, JsonGenerator json)
      throws IOException, SerializerException {

    for (final Link link : linked.getNavigationLinks()) {
      final String name = link.getTitle();
      for (final Annotation annotation : link.getAnnotations()) {
        valuable(json, annotation, name + '@' + annotation.getTerm(), null, null);
      }

      final EdmEntityType targetType =
          entityType == null || name == null || entityType.getNavigationProperty(name) == null ? null : entityType
              .getNavigationProperty(name).getType();
      if (link.getInlineEntity() != null) {
        json.writeFieldName(name);
        doSerialize(targetType, link.getInlineEntity(), null, null, json);
      } else if (link.getInlineEntitySet() != null) {
        json.writeArrayFieldStart(name);
        for (final Entity subEntry : link.getInlineEntitySet().getEntities()) {
          doSerialize(targetType, subEntry, null, null, json);
        }
        json.writeEndArray();
      }
    }
  }

  private void collection(final JsonGenerator json, final EdmType itemType, final String typeName,
      final EdmProperty edmProperty, final ValueType valueType, final List<?> value)
      throws IOException, SerializerException {

    json.writeStartArray();

    for (final Object item : value) {
      switch (valueType) {
      case COLLECTION_PRIMITIVE:
        primitiveValue(json, (EdmPrimitiveType) itemType, typeName, edmProperty, item);
        break;

      case COLLECTION_GEOSPATIAL:
      case COLLECTION_ENUM:
        throw new SerializerException("Geo and enum types are not supported.", MessageKeys.NOT_IMPLEMENTED);

      case COLLECTION_COMPLEX:
        complexValue(json, (EdmComplexType) itemType, typeName, (ComplexValue) item);
        break;

      default:
      }
    }

    json.writeEndArray();
  }

  protected void primitiveValue(final JsonGenerator json, final EdmPrimitiveType valueType, final String typeName,
      final EdmProperty edmProperty, final Object value) throws IOException, SerializerException {

    EdmPrimitiveType type = valueType;
    if (type == null) {
      final EdmPrimitiveTypeKind kind =
          typeName == null ? EdmTypeInfo.determineTypeKind(value) : new EdmTypeInfo.Builder().setTypeExpression(
              typeName).build().getPrimitiveTypeKind();
      type = kind == null ? null : EdmPrimitiveTypeFactory.getInstance(kind);
    }

    if (value == null) {
      json.writeNull();
    } else if (type == null) {
      throw new SerializerException("The primitive type could not be determined.",
          MessageKeys.INCONSISTENT_PROPERTY_TYPE, "");
    } else if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean)) {
      json.writeBoolean((Boolean) value);
    } else {
      String serialized = null;
      try {
    	  Integer scale = null;
    	  if (value instanceof BigDecimal) {
    		  scale = ((BigDecimal) value).scale();
    	  } else {
    		  scale = Constants.DEFAULT_SCALE;
    	  }
        serialized = type.valueToString(value,
            edmProperty == null ? null : edmProperty.isNullable(),
            edmProperty == null ? null : edmProperty.getMaxLength(),
            edmProperty == null ? null : edmProperty.getPrecision(),
            edmProperty == null ? scale : edmProperty.getScale(),
            edmProperty == null ? null : edmProperty.isUnicode());
      } catch (final EdmPrimitiveTypeException e) {
        final String name = edmProperty == null ? "" : edmProperty.getName();
        throw new SerializerException("Wrong value for property '" + name + "'!", e,
            SerializerException.MessageKeys.WRONG_PROPERTY_VALUE, name, value.toString());
      }
      if (isIEEE754Compatible &&
          (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int64)
              || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal))
          || type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Byte)
              && type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.SByte)
              && type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Single)
              && type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Double)
              && type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int16)
              && type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int32)
              && type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int64)
              && type != EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal)) {
        json.writeString(serialized);
      } else {
        json.writeNumber(serialized);
      }
    }
  }

  private void complexValue(final JsonGenerator json, final EdmComplexType valueType, final String typeName,
      final ComplexValue value) throws IOException, SerializerException {
    json.writeStartObject();

    if (typeName != null && isODataMetadataFull) {
      json.writeStringField(constants.getType(), typeName);
    }

    for (final Property property : value.getValue()) {
      final String name = property.getName();
      final EdmProperty edmProperty = valueType == null || valueType.getStructuralProperty(name) == null ? null
          : valueType.getStructuralProperty(name);
      valuable(json, property, name, edmProperty == null ? null : edmProperty.getType(), edmProperty);
    }
    links(value, null, json);

    json.writeEndObject();
  }

  private void value(final JsonGenerator json, final Valuable value, final EdmType type, final EdmProperty edmProperty)
      throws IOException, SerializerException {
    final String typeName = value.getType() == null ? null : new EdmTypeInfo.Builder().setTypeExpression(value
        .getType()).build().external();

    if (value.isNull()) {
      json.writeNull();
    } else if (value.isCollection()) {
      collection(json, type, typeName, edmProperty, value.getValueType(), value.asCollection());
    } else if (value.isPrimitive()) {
      primitiveValue(json, (EdmPrimitiveType) type, typeName, edmProperty, value.asPrimitive());
    } else if (value.isComplex()) {
      complexValue(json, (EdmComplexType) type, typeName, value.asComplex());
    } else if (value.isEnum() || value.isGeospatial()) {
      throw new SerializerException("Geo and enum types are not supported.", MessageKeys.NOT_IMPLEMENTED);
    }
  }

  protected void valuable(JsonGenerator json, final Valuable valuable, final String name, final EdmType type,
      final EdmProperty edmProperty) throws IOException, SerializerException {

    if (isODataMetadataFull
        && !(valuable instanceof Annotation) && !valuable.isComplex()) {

      String typeName = valuable.getType();
      if (typeName == null && type == null && valuable.isPrimitive()) {
        if (valuable.isCollection()) {
          if (!valuable.asCollection().isEmpty()) {
            final EdmPrimitiveTypeKind kind = EdmTypeInfo.determineTypeKind(valuable.asCollection().get(0));
            if (kind != null) {
              typeName = "Collection(" + kind.getFullQualifiedName().getFullQualifiedNameAsString() + ')';
            }
          }
        } else {
          final EdmPrimitiveTypeKind kind = EdmTypeInfo.determineTypeKind(valuable.asPrimitive());
          if (kind != null) {
            typeName = kind.getFullQualifiedName().getFullQualifiedNameAsString();
          }
        }
      }
      
      if (typeName != null) {
        json.writeStringField(name + constants.getType(), constructTypeExpression(typeName));
      }
    }

    for (final Annotation annotation : ((Annotatable) valuable).getAnnotations()) {
      valuable(json, annotation, name + '@' + annotation.getTerm(), null, null);
    }

    json.writeFieldName(name);
    value(json, valuable, type, edmProperty);
  }

  private String constructTypeExpression(String typeName) {
    EdmTypeInfo typeInfo = new EdmTypeInfo.Builder().setTypeExpression(typeName).build();
    StringBuilder stringBuilder = new StringBuilder();

    if (typeInfo.isCollection()) {
      stringBuilder.append("#Collection(");
    } else {
      stringBuilder.append('#');
    }

    stringBuilder.append(typeInfo.isPrimitiveType() ? typeInfo.getFullQualifiedName().getName() : typeInfo
        .getFullQualifiedName().getFullQualifiedNameAsString());

    if (typeInfo.isCollection()) {
      stringBuilder.append(')');
    }

    return stringBuilder.toString();
  }
}
