/*
 * Copyright (c) 2011, 2020 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:
//      gonural - Initial implementation
//      Dmitry Kornilov - JPARS 2.0 related changes
package org.eclipse.persistence.jpa.rs.resources.common;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.naming.InitialContext;
import javax.naming.NamingException;
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 jakarta.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.Link;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.Parameter;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.SessionBeanCall;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.v2.ContextsCatalog;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.v2.Resource;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
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.features.ServiceVersion;
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.jpa.rs.util.list.LinkList;

/**
 * Base class for persistent unit resources.
 *
 * @author gonural
 */
public abstract class AbstractPersistenceResource extends AbstractResource {
    private static final String CLASS_NAME = AbstractPersistenceResource.class.getName();

    /**
     * Produces a response containing a list of available persistence contexts.
     * Returns different responses depending version.
     *
     * @param version the service version (null, "v1.0", "v2.0", "latest")
     * @param headers the HTTP headers
     * @param uriInfo the URL
     * @return response containing a list of persistence contexts.
     */
    protected Response getContextsInternal(String version, HttpHeaders headers, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "getContextsInternal", new Object[] { "GET", version, uriInfo.getRequestUri().toASCIIString() });
        if (!isValidVersion(version)) {
            JPARSLogger.error("unsupported_service_version_in_the_request", new Object[] { version });
            throw JPARSException.invalidServiceVersion(version);
        }

        if (ServiceVersion.fromCode(version).compareTo(ServiceVersion.VERSION_2_0) >= 0) {
            return getContextsV2(version, headers, uriInfo);
        } else {
            return getContextsV1(version, headers, uriInfo);
        }
    }

    @SuppressWarnings("rawtypes")
    protected Response callSessionBeanInternal(String version, HttpHeaders headers, UriInfo uriInfo, InputStream is) {
        JPARSLogger.entering(CLASS_NAME, "callSessionBeanInternal", new Object[] { "POST", headers.getMediaType(), version, uriInfo.getRequestUri().toASCIIString() });
        try {
            if (!isValidVersion(version)) {
                JPARSLogger.error("unsupported_service_version_in_the_request", new Object[] { version });
                throw JPARSException.invalidServiceVersion(version);
            }

            SessionBeanCall call = unmarshallSessionBeanCall(is);

            String jndiName = call.getJndiName();
            if (!isValid(jndiName)) {
                JPARSLogger.error("jpars_invalid_jndi_name", new Object[] { jndiName });
                throw JPARSException.jndiNamePassedIsInvalid(jndiName);
            }
            
            javax.naming.Context ctx = new InitialContext();
            Object ans = ctx.lookup(jndiName);
            if (ans == null) {
                JPARSLogger.error("jpars_could_not_find_session_bean", new Object[] { jndiName });
                throw JPARSException.sessionBeanCouldNotBeFound(jndiName);
            }

            PersistenceContext context = null;
            if (call.getContext() != null) {
                context = getPersistenceFactory().get(call.getContext(), uriInfo.getBaseUri(), version, null);
                if (context == null) {
                    JPARSLogger.error("jpars_could_not_find_persistence_context", new Object[] { call.getContext() });
                    throw JPARSException.persistenceContextCouldNotBeBootstrapped(call.getContext());
                }
            }

            Class[] parameters = new Class[call.getParameters().size()];
            Object[] args = new Object[call.getParameters().size()];
            int i = 0;
            for (Parameter param : call.getParameters()) {
                Class parameterClass = null;
                Object parameterValue;
                if (context != null) {
                    parameterClass = context.getClass(param.getTypeName());
                }
                if (parameterClass != null) {
                    parameterValue = context.unmarshalEntity(param.getTypeName(), headers.getMediaType(), is);
                } else {
                    parameterClass = Thread.currentThread().getContextClassLoader().loadClass(param.getTypeName());
                    parameterValue = ConversionManager.getDefaultManager().convertObject(param.getValue(), parameterClass);
                }
                parameters[i] = parameterClass;
                args[i] = parameterValue;
                i++;
            }
            Method method = ans.getClass().getMethod(call.getMethodName(), parameters);
            Object returnValue = method.invoke(ans, args);
            return Response.ok(new StreamingOutputMarshaller(null, returnValue, headers.getAcceptableMediaTypes())).build();
        } catch (JAXBException | NamingException | ReflectiveOperationException | RuntimeException e) {
            JPARSLogger.exception("exception_in_callSessionBeanInternal", new Object[]{version, headers.getMediaType(), uriInfo.getRequestUri().toASCIIString()}, e);
            throw JPARSException.exceptionOccurred(e);
        }
    }

    private boolean isValid(String jndiName) {
        String protocol = null;
        int colon = jndiName.indexOf(':');
        int slash = jndiName.indexOf('/');
        if (colon > 0 && (slash == -1 || colon < slash)) {
            protocol = jndiName.substring(0, colon);
        }
        return protocol == null || protocol.isEmpty() || protocol.equalsIgnoreCase("java") || protocol.equalsIgnoreCase("ejb");
    }

    private SessionBeanCall unmarshallSessionBeanCall(InputStream data) throws JAXBException {
        Class<?>[] jaxbClasses = new Class[] { SessionBeanCall.class };
        JAXBContext context = (JAXBContext) JAXBContextFactory.createContext(jaxbClasses, null);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, Boolean.FALSE);
        unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
        StreamSource ss = new StreamSource(data);
        return unmarshaller.unmarshal(ss, SessionBeanCall.class).getValue();
    }

    /**
     * Returns a response object containing the available contexts list. Used in JPARS 1.0 and below.
     *
     * @param version the version (null or "v1.0")
     * @param headers the HTTP headers
     * @param uriInfo the UTL info
     * @return Response object
     */
    private Response getContextsV1(String version, HttpHeaders headers, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "getContextsV1", new Object[] { "GET", version, uriInfo.getRequestUri().toASCIIString() });
        try {
            final Set<String> contexts = getPersistenceFactory().getPersistenceContextNames();
            final String mediaType = StreamingOutputMarshaller.mediaType(headers.getAcceptableMediaTypes()).toString();
            final URI baseURI = uriInfo.getBaseUri();
            final List<Link> links = new ArrayList<>();

            for (String context : contexts) {
                if (version != null) {
                    links.add(new Link(context, mediaType, baseURI + version + "/" + context + "/metadata"));
                } else {
                    links.add(new Link(context, mediaType, baseURI + context + "/metadata"));
                }
            }

            final LinkList linkList = new LinkList();
            linkList.setList(links);

            final String result;
            if (mediaType.equals(MediaType.APPLICATION_JSON)) {
                result = marshallMetadata(linkList.getList(), mediaType);
            } else {
                result = marshallMetadata(linkList, mediaType);
            }
            return Response.ok(new StreamingOutputMarshaller(null, result, headers.getAcceptableMediaTypes())).build();
        } catch (JAXBException ex) {
            JPARSLogger.exception("exception_in_getContextsV1", new Object[] {version, headers.getMediaType(), uriInfo.getRequestUri().toASCIIString()}, ex);
            throw JPARSException.exceptionOccurred(ex);
        }
    }

    /**
     * Returns a response object containing the available contexts list. Used in JPARS 2.0 or above.
     *
     * @param version the version ("v2.0" or higher)
     * @param headers the HTTP headers
     * @param uriInfo the UTL info
     * @return Response object
     */
    private Response getContextsV2(String version, HttpHeaders headers, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "getContextsV2", new Object[] { "GET", version, uriInfo.getRequestUri().toASCIIString() });
        try {
            final ContextsCatalog result = new ContextsCatalog();

            final Set<String> contexts = getPersistenceFactory().getPersistenceContextNames();
            for (String context : contexts) {
                final Resource contextResource = new Resource();
                contextResource.setName(context);

                final String href = HrefHelper.getRoot(uriInfo.getBaseUri().toString(), version, context).append("/metadata-catalog").toString();
                contextResource.setLinks((new ItemLinksBuilder())
                        .addCanonical(href)
                        .getList());

                result.addContext(contextResource);
            }

            final String mediaType = StreamingOutputMarshaller.mediaType(headers.getAcceptableMediaTypes()).toString();
            final String marshalled = marshallMetadata(result, mediaType);

            return Response.ok(new StreamingOutputMarshaller(null, marshalled, headers.getAcceptableMediaTypes())).build();
        } catch (JAXBException ex) {
            JPARSLogger.exception("exception_in_getContextsV2", new Object[] {version, headers.getMediaType(), uriInfo.getRequestUri().toASCIIString()}, ex);
            throw JPARSException.exceptionOccurred(ex);
        }
    }
}
