/*
 * Copyright (c) 2014, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Dmitry Kornilov - Initial implementation
package org.eclipse.persistence.jpa.rs.resources;

import static org.eclipse.persistence.jpa.rs.resources.common.AbstractResource.SERVICE_VERSION_FORMAT;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriInfo;
import jakarta.xml.bind.JAXBException;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.eis.mappings.EISCompositeCollectionMapping;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.internal.expressions.MapEntryExpression;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.LinkV2;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.v2.MetadataCatalog;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.v2.Property;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.v2.Reference;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.v2.Resource;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.v2.ResourceSchema;
import org.eclipse.persistence.internal.queries.ReportItem;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.rs.PersistenceContext;
import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
import org.eclipse.persistence.jpa.rs.features.ItemLinksBuilder;
import org.eclipse.persistence.jpa.rs.resources.common.AbstractResource;
import org.eclipse.persistence.jpa.rs.util.HrefHelper;
import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
import org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ReportQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;

/**
 * JPARS 2.0 metadata catalog. Resource metadata and schemas.
 *
 * @author Dmitry Kornilov
 * @since EclipseLink 2.6.0.
 */
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Path("/{version : " + SERVICE_VERSION_FORMAT + "}/{context}/metadata-catalog/")
public class MetadataResource extends AbstractResource {
    private static final String CLASS_NAME = MetadataResource.class.getName();
    private static final Map<Class<?>, String> PRIMITIVE_TO_JSON = new HashMap<Class<?>, String>();

    static {
        PRIMITIVE_TO_JSON.put(boolean.class, "boolean");
        PRIMITIVE_TO_JSON.put(byte.class, "number");
        PRIMITIVE_TO_JSON.put(char.class, "string");
        PRIMITIVE_TO_JSON.put(double.class, "number");
        PRIMITIVE_TO_JSON.put(float.class, "number");
        PRIMITIVE_TO_JSON.put(int.class, "integer");
        PRIMITIVE_TO_JSON.put(long.class, "integer");
        PRIMITIVE_TO_JSON.put(short.class, "number");
        PRIMITIVE_TO_JSON.put(short.class, "number");
    }

    /**
     * Returns metadata catalog.
     */
    @GET
    public Response getMetadataCatalog(@PathParam("version") String version,
                                       @PathParam("context") String persistenceUnit,
                                       @Context HttpHeaders httpHeaders,
                                       @Context UriInfo uriInfo) {
        setRequestUniqueId();
        return buildMetadataCatalogResponse(version, persistenceUnit, httpHeaders, uriInfo);
    }

    /**
     * Returns entity metadata if accepted media type is 'application/json' or entity schema if
     * accepted media type is 'application/schema+json'.
     */
    @GET
    @Produces({ MediaType.APPLICATION_JSON, AbstractResource.APPLICATION_SCHEMA_JSON })
    @Consumes({ MediaType.APPLICATION_JSON, AbstractResource.APPLICATION_SCHEMA_JSON })
    @Path("entity/{entityName}")
    public Response getEntityResource(@PathParam("version") String version,
                                      @PathParam("context") String persistenceUnit,
                                      @PathParam("entityName") String entityName,
                                      @Context HttpHeaders httpHeaders,
                                      @Context UriInfo uriInfo) {
        setRequestUniqueId();
        final MediaType mediaType = StreamingOutputMarshaller.mediaType(httpHeaders.getAcceptableMediaTypes());

        // Return schema if application.schema+json media type is requested otherwise return entity metadata
        if (mediaType.equals(AbstractResource.APPLICATION_SCHEMA_JSON_TYPE)) {
            return buildEntitySchemaResponse(version, persistenceUnit, entityName, uriInfo);
        } else {
            return buildEntityMetadataResponse(version, persistenceUnit, entityName, httpHeaders, uriInfo);
        }
    }

    /**
     * Returns query metadata if accepted media type is 'application/json' or entity schema if
     * accepted media type is 'application/schema+json'.
     */
    @GET
    @Produces({ MediaType.APPLICATION_JSON, AbstractResource.APPLICATION_SCHEMA_JSON })
    @Consumes({ MediaType.APPLICATION_JSON, AbstractResource.APPLICATION_SCHEMA_JSON })
    @Path("query/{queryName}")
    public Response getQueryResource(@PathParam("version") String version,
                                     @PathParam("context") String persistenceUnit,
                                     @PathParam("queryName") String queryName,
                                     @Context HttpHeaders httpHeaders,
                                     @Context UriInfo uriInfo) {
        setRequestUniqueId();
        final MediaType mediaType = StreamingOutputMarshaller.mediaType(httpHeaders.getAcceptableMediaTypes());

        // Return schema if application.schema+json media type is requested otherwise return entity metadata
        if (mediaType.equals(AbstractResource.APPLICATION_SCHEMA_JSON_TYPE)) {
            return buildQuerySchemaResponse(version, persistenceUnit, queryName, uriInfo);
        } else {
            return buildQueryMetadataResponse(version, persistenceUnit, queryName, httpHeaders, uriInfo);
        }
    }

    private Response buildMetadataCatalogResponse(String version, String persistenceUnit, HttpHeaders httpHeaders, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "buildMetadataCatalogResponse", new Object[]{"GET", version, persistenceUnit, uriInfo.getRequestUri().toASCIIString()});

        final String result;
        try {
            final PersistenceContext context = getPersistenceContext(persistenceUnit, null, uriInfo.getBaseUri(), version, null);
            final MetadataCatalog catalog = buildMetadataCatalog(context);
            final String mediaType = StreamingOutputMarshaller.mediaType(httpHeaders.getAcceptableMediaTypes()).toString();
            result = marshallMetadata(catalog, mediaType);
        } catch (JAXBException e) {
            throw JPARSException.exceptionOccurred(e);
        }
        return Response.ok(new StreamingOutputMarshaller(null, result, httpHeaders.getAcceptableMediaTypes())).build();
    }

    private Response buildEntityMetadataResponse(String version, String persistenceUnit, String entityName, HttpHeaders httpHeaders, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "buildEntityMetadataResponse", new Object[]{"GET", version, persistenceUnit, entityName, uriInfo.getRequestUri().toASCIIString()});

        final String result;
        try {
            final PersistenceContext context = getPersistenceContext(persistenceUnit, null, uriInfo.getBaseUri(), version, null);
            final ClassDescriptor descriptor = context.getServerSession().getDescriptorForAlias(entityName);
            if (descriptor == null) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_entity_type", new Object[] { entityName, persistenceUnit });
                throw JPARSException.classOrClassDescriptorCouldNotBeFoundForEntity(entityName, persistenceUnit);
            } else {
                final String mediaType = StreamingOutputMarshaller.mediaType(httpHeaders.getAcceptableMediaTypes()).toString();
                final Resource resource = buildEntityMetadata(context, descriptor);
                result = marshallMetadata(resource, mediaType);
            }
        } catch (JAXBException e) {
            throw JPARSException.exceptionOccurred(e);
        }
        return Response.ok(new StreamingOutputMarshaller(null, result, httpHeaders.getAcceptableMediaTypes())).build();
    }

    private Response buildQueryMetadataResponse(String version, String persistenceUnit, String queryName, HttpHeaders httpHeaders, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "buildQueryMetadataResponse", new Object[]{"GET", version, persistenceUnit, queryName, uriInfo.getRequestUri().toASCIIString()});

        final String result;
        try {
            final PersistenceContext context = getPersistenceContext(persistenceUnit, null, uriInfo.getBaseUri(), version, null);

            // We need to make sure that query with given name exists
            final DatabaseQuery query = context.getServerSession().getQuery(queryName);
            if (query == null) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_query", new Object[] {queryName, persistenceUnit});
                throw JPARSException.responseCouldNotBeBuiltForNamedQueryRequest(queryName, context.getName());
            }

            final String mediaType = StreamingOutputMarshaller.mediaType(httpHeaders.getAcceptableMediaTypes()).toString();
            final Resource resource = buildQueryMetadata(context, query);
            result = marshallMetadata(resource, mediaType);
        } catch (JAXBException e) {
            throw JPARSException.exceptionOccurred(e);
        }
        return Response.ok(new StreamingOutputMarshaller(null, result, httpHeaders.getAcceptableMediaTypes())).build();
    }

    private Response buildEntitySchemaResponse(String version, String persistenceUnit, String entityName, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "buildEntitySchemaResponse", new Object[]{"GET", version, persistenceUnit, uriInfo.getRequestUri().toASCIIString()});

        final String result;
        try {
            final PersistenceContext context = getPersistenceContext(persistenceUnit, null, uriInfo.getBaseUri(), version, null);
            final ClassDescriptor descriptor = context.getServerSession().getDescriptorForAlias(entityName);
            if (descriptor == null) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_entity_type", new Object[] { entityName, persistenceUnit });
                throw JPARSException.classOrClassDescriptorCouldNotBeFoundForEntity(entityName, persistenceUnit);
            } else {
                final ResourceSchema schema = new ResourceSchema();
                schema.setTitle(descriptor.getAlias());
                schema.setSchema(HrefHelper.buildEntityMetadataHref(context, descriptor.getAlias()) + "#");
                schema.addAllOf(new Reference(HrefHelper.buildBaseRestSchemaRef("#/singularResource")));

                // Properties
                for (DatabaseMapping databaseMapping : descriptor.getMappings()) {
                    schema.addProperty(databaseMapping.getAttributeName(), buildProperty(context, databaseMapping));
                }

                // Links
                final String instancesHref = HrefHelper.buildEntityDescribesHref(context, descriptor.getAlias());
                schema.setLinks((new ItemLinksBuilder())
                        .addDescribedBy(HrefHelper.buildEntityMetadataHref(context, descriptor.getAlias()))
                        .addFind(instancesHref + "/{primaryKey}")
                        .addCreate(instancesHref)
                        .addUpdate(instancesHref)
                        .addDelete(instancesHref + "/{primaryKey}")
                        .getList());

                result = marshallMetadata(schema, MediaType.APPLICATION_JSON);
            }
        } catch (JAXBException e) {
            throw JPARSException.exceptionOccurred(e);
        }
        return Response.ok(new StreamingOutputMarshaller(null, result, AbstractResource.APPLICATION_SCHEMA_JSON_TYPE)).build();
    }

    private Response buildQuerySchemaResponse(String version, String persistenceUnit, String queryName, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "buildQuerySchemaResponse", new Object[]{"GET", version, persistenceUnit, uriInfo.getRequestUri().toASCIIString()});

        final String result;
        try {
            final PersistenceContext context = getPersistenceContext(persistenceUnit, null, uriInfo.getBaseUri(), version, null);

            // We need to make sure that query with given name exists
            final DatabaseQuery query = context.getServerSession().getQuery(queryName);
            if (query == null) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_query", new Object[] {queryName, persistenceUnit});
                throw JPARSException.responseCouldNotBeBuiltForNamedQueryRequest(queryName, context.getName());
            }

            final ResourceSchema querySchema = buildQuerySchema(context, query);
            result = marshallMetadata(querySchema, MediaType.APPLICATION_JSON);
        } catch (JAXBException e) {
            throw JPARSException.exceptionOccurred(e);
        }
        return Response.ok(new StreamingOutputMarshaller(null, result, AbstractResource.APPLICATION_SCHEMA_JSON_TYPE)).build();
    }

    private MetadataCatalog buildMetadataCatalog(PersistenceContext context) {
        final MetadataCatalog result = new MetadataCatalog();

        // Entities
        final Map<Class<?>, ClassDescriptor> descriptors = context.getServerSession().getDescriptors();
        for (ClassDescriptor descriptor : descriptors.values()) {

            // Skip embeddables
            if (!descriptor.isAggregateDescriptor()) {
                result.addResource(buildEntityMetadata(context, descriptor));
            }
        }

        // Queries
        final Map<String, List<DatabaseQuery>> allQueries = context.getServerSession().getQueries();
        for (List<DatabaseQuery> databaseQueries : allQueries.values()) {
            if (databaseQueries != null) {
                for (DatabaseQuery query : databaseQueries) {
                    if (query.getReferenceClassName() != null) {
                        result.addResource(buildQueryMetadata(context, query));
                    }
                }
            }
        }

        final String href = HrefHelper.buildMetadataCatalogHref(context);
        final List<LinkV2> links = (new ItemLinksBuilder())
                .addCanonical(href)
                .getList();

        result.setLinks(links);
        return result;
    }

    private Resource buildEntityMetadata(PersistenceContext context, ClassDescriptor descriptor) {
        final Resource resource = new Resource();
        resource.setName(descriptor.getAlias());

        final String metadataHref = HrefHelper.buildEntityMetadataHref(context, descriptor.getAlias());
        final List<LinkV2> links = (new ItemLinksBuilder())
                .addAlternate(metadataHref)
                .addCanonical(metadataHref, MediaType.APPLICATION_JSON)
                .addDescribes(HrefHelper.buildEntityDescribesHref(context, descriptor.getAlias()))
                .getList();

        resource.setLinks(links);
        return resource;
    }

    private Resource buildQueryMetadata(PersistenceContext context, DatabaseQuery query) {
        final Resource resource = new Resource();
        resource.setName(query.getName());

        final String metadataHref = HrefHelper.buildQueryMetadataHref(context, query.getName());
        final List<LinkV2> links = (new ItemLinksBuilder())
                .addAlternate(metadataHref)
                .addCanonical(metadataHref, MediaType.APPLICATION_JSON)
                .addDescribes(HrefHelper.buildQueryDescribesHref(context, query.getName()))
                .getList();

        resource.setLinks(links);
        return resource;
    }

    private ResourceSchema buildQuerySchema(PersistenceContext context, DatabaseQuery query) {
        final ResourceSchema schema = new ResourceSchema();
        schema.setTitle(query.getName());
        schema.setSchema(HrefHelper.buildQueryMetadataHref(context, query.getName()) + "#");
        schema.addAllOf(new Reference(HrefHelper.buildBaseRestSchemaRef("#/collectionBaseResource")));

        // Link
        final String method = query.isReadQuery() ? "GET" : "POST";
        schema.setLinks((new ItemLinksBuilder())
                .addExecute(HrefHelper.buildQueryHref(context, query.getName(), getQueryParamString(query)), method)
                .getList());

        // Definitions
        if (query.isReportQuery()) {
            // In case of report query we need to define a returned type
            final ResourceSchema returnType = new ResourceSchema();

            query.checkPrepare((AbstractSession) context.getServerSession(), new DatabaseRecord());
            for (ReportItem item : ((ReportQuery) query).getItems()) {
                final Property property;
                if (item.getMapping() != null) {
                    if (item.getAttributeExpression() != null && item.getAttributeExpression().isMapEntryExpression()) {
                        if (((MapEntryExpression)item.getAttributeExpression()).shouldReturnMapEntry()) {
                            property = buildProperty(context, Map.Entry.class);
                        } else {
                            property = buildProperty(context, ((Class<?>) item.getMapping().getContainerPolicy().getKeyType()));
                        }
                    } else {
                        property = buildProperty(context, item.getMapping().getAttributeClassification());
                    }
                } else if (item.getResultType() != null) {
                    property = buildProperty(context, item.getResultType());
                } else if (item.getDescriptor() != null) {
                    property = buildProperty(context, item.getDescriptor().getJavaClass());
                } else if (item.getAttributeExpression() != null && item.getAttributeExpression().isConstantExpression()) {
                    property = buildProperty(context, ((ConstantExpression) item.getAttributeExpression()).getValue().getClass());
                } else {
                    // Use Object.class by default.
                    property = buildProperty(context, Object.class);
                }
                returnType.addProperty(item.getName(), property);
            }
            schema.addDefinition("result", returnType);

            final Property items = new Property();
            items.setType("array");
            items.setItems(new Property("#/definitions/result"));
            schema.addProperty("items", items);
        } else {
            // Read all query. Each item is an entity. Make a JSON pointer.
            if (query.getReferenceClassName() != null) {
                final Property items = new Property();
                items.setType("array");
                items.setItems(new Property(HrefHelper.buildEntityMetadataHref(context, query.getReferenceClass().getSimpleName()) + "#"));
                schema.addProperty("items", items);
            }
        }

        return schema;
    }

    private String getQueryParamString(DatabaseQuery query) {
        final StringBuilder queryParams = new StringBuilder();
        for (String arg : query.getArguments()) {
            queryParams.append(";");
            queryParams.append(arg).append("={").append(arg).append("}");
        }
        return queryParams.toString();
    }

    private Property buildProperty(PersistenceContext context, DatabaseMapping mapping) {
        if (mapping.isCollectionMapping()) {
            final Property property = new Property();
            property.setType("array");
            property.setItems(buildProperty(context, getCollectionGenericClass(mapping)));
            return property;
        } else if (mapping.isForeignReferenceMapping()) {
            final ForeignReferenceMapping foreignReferenceMapping = (ForeignReferenceMapping)mapping;
            final String href = HrefHelper.buildEntityMetadataHref(context, foreignReferenceMapping.getReferenceClass().getSimpleName() + "#");
            return new Property(href);
        } else {
            return buildProperty(context, mapping.getAttributeClassification());
        }
    }

    private Property buildProperty(PersistenceContext context, Class<?> clazz) {
        final Property property = new Property();
        if (context.getServerSession().getDescriptorForAlias(clazz.getSimpleName()) != null) {
            property.setRef(HrefHelper.buildEntityMetadataHref(context, clazz.getSimpleName()) + "#");
        } else if (Number.class.isAssignableFrom(clazz)) {
            property.setType("number");
        } else if (Boolean.class.equals(clazz)) {
            property.setType("boolean");
        } else if (String.class.equals(clazz)) {
            property.setType("string");
        } else if (Collection.class.isAssignableFrom(clazz)) {
            property.setType("array");
        } else if (clazz.isPrimitive()) {
            property.setType(PRIMITIVE_TO_JSON.get(clazz));
        } else {
            property.setType("object");
        }

        return property;
    }

    private Class<?> getCollectionGenericClass(DatabaseMapping mapping) {
        Class<?> collectionName = null;
        if (mapping.isEISMapping()) {
            final EISCompositeCollectionMapping collectionMapping = (EISCompositeCollectionMapping) mapping;
            if (collectionMapping.getReferenceClass() != null) {
                collectionName = collectionMapping.getReferenceClass();
            }
            if ((collectionName == null) && (collectionMapping.getAttributeClassification() != null)) {
                collectionName = collectionMapping.getAttributeClassification();
            }
        } else {
            final CollectionMapping collectionMapping = (CollectionMapping) mapping;
            if (collectionMapping.getReferenceClass() != null) {
                collectionName = collectionMapping.getReferenceClass();
            }
            if ((collectionName == null) && (collectionMapping.getAttributeClassification() != null)) {
                collectionName = collectionMapping.getAttributeClassification();
            }
        }

        return collectionName;
    }
}
