/*
 * Copyright (c) 2012, 2019 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.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.jdkhttp;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.Principal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.ws.rs.core.Application;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriBuilder;

import org.glassfish.jersey.internal.MapPropertiesDelegate;
import org.glassfish.jersey.jdkhttp.internal.LocalizationMessages;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.ContainerException;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.ContainerResponse;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.spi.Container;
import org.glassfish.jersey.server.spi.ContainerResponseWriter;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsExchange;

/**
 * Jersey {@code Container} implementation based on Java SE {@link HttpServer}.
 *
 * @author Miroslav Fuksa
 * @author Marek Potociar
 */
public class JdkHttpHandlerContainer implements HttpHandler, Container {

    private static final Logger LOGGER = Logger.getLogger(JdkHttpHandlerContainer.class.getName());

    private volatile ApplicationHandler appHandler;

    /**
     * Create new lightweight Java SE HTTP server container.
     *
     * @param application JAX-RS / Jersey application to be deployed on the container.
     */
    JdkHttpHandlerContainer(final Application application) {
        this.appHandler = new ApplicationHandler(application);
    }

    /**
     * Create new lightweight Java SE HTTP server container.
     *
     * @param application   JAX-RS / Jersey application to be deployed on the container.
     * @param parentContext DI provider specific context with application's registered bindings.
     */
    JdkHttpHandlerContainer(final Application application, final Object parentContext) {
        this.appHandler = new ApplicationHandler(application, null, parentContext);
    }

    @Override
    public void handle(final HttpExchange exchange) throws IOException {
        /**
         * This is a URI that contains the path, query and fragment components.
         */
        URI exchangeUri = exchange.getRequestURI();

        /**
         * The base path specified by the HTTP context of the HTTP handler. It
         * is in decoded form.
         */
        String decodedBasePath = exchange.getHttpContext().getPath();

        // Ensure that the base path ends with a '/'
        if (!decodedBasePath.endsWith("/")) {
            if (decodedBasePath.equals(exchangeUri.getPath())) {
                /**
                 * This is an edge case where the request path does not end in a
                 * '/' and is equal to the context path of the HTTP handler.
                 * Both the request path and base path need to end in a '/'
                 * Currently the request path is modified.
                 *
                 * TODO support redirection in accordance with resource configuration feature.
                 */
                exchangeUri = UriBuilder.fromUri(exchangeUri)
                        .path("/").build();
            }
            decodedBasePath += "/";
        }

        /*
         * The following is madness, there is no easy way to get the complete
         * URI of the HTTP request!!
         *
         * TODO this is missing the user information component, how can this be obtained?
         */
        final boolean isSecure = exchange instanceof HttpsExchange;
        final String scheme = isSecure ? "https" : "http";

        final URI baseUri = getBaseUri(exchange, decodedBasePath, scheme);
        final URI requestUri = getRequestUri(exchange, baseUri);

        final ResponseWriter responseWriter = new ResponseWriter(exchange);
        final ContainerRequest requestContext = new ContainerRequest(baseUri, requestUri,
                exchange.getRequestMethod(), getSecurityContext(exchange.getPrincipal(), isSecure),
                new MapPropertiesDelegate());
        requestContext.setEntityStream(exchange.getRequestBody());
        requestContext.getHeaders().putAll(exchange.getRequestHeaders());
        requestContext.setWriter(responseWriter);
        try {
            appHandler.handle(requestContext);
        } finally {
            // if the response was not committed yet by the JerseyApplication
            // then commit it and log warning
            responseWriter.closeAndLogWarning();
        }
    }

    private URI getBaseUri(final HttpExchange exchange, final String decodedBasePath, final String scheme) {
        final URI baseUri;
        try {
            final List<String> hostHeader = exchange.getRequestHeaders().get("Host");
            if (hostHeader != null) {
                baseUri = new URI(scheme + "://" + hostHeader.get(0) + decodedBasePath);
            } else {
                final InetSocketAddress addr = exchange.getLocalAddress();
                baseUri = new URI(scheme, null, addr.getHostName(), addr.getPort(),
                        decodedBasePath, null, null);
            }
        } catch (final URISyntaxException ex) {
            throw new IllegalArgumentException(ex);
        }
        return baseUri;
    }

    private URI getRequestUri(final HttpExchange exchange, final URI baseUri) {
        try {
            return new URI(getServerAddress(baseUri) + exchange.getRequestURI());
        } catch (URISyntaxException ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    private String getServerAddress(final URI baseUri) throws URISyntaxException {
        return new URI(baseUri.getScheme(), null,  baseUri.getHost(), baseUri.getPort(), null, null, null).toString();
    }

    private SecurityContext getSecurityContext(final Principal principal, final boolean isSecure) {
        return new SecurityContext() {

            @Override
            public boolean isUserInRole(final String role) {
                return false;
            }

            @Override
            public boolean isSecure() {
                return isSecure;
            }

            @Override
            public Principal getUserPrincipal() {
                return principal;
            }

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

    @Override
    public ResourceConfig getConfiguration() {
        return appHandler.getConfiguration();
    }

    @Override
    public void reload() {
        reload(getConfiguration());
    }

    @Override
    public void reload(final ResourceConfig configuration) {
        appHandler.onShutdown(this);

        appHandler = new ApplicationHandler(configuration);
        appHandler.onReload(this);
        appHandler.onStartup(this);
    }

    @Override
    public ApplicationHandler getApplicationHandler() {
        return appHandler;
    }

    /**
     * Inform this container that the server has been started.
     *
     * This method must be implicitly called after the server containing this container is started.
     */
    void onServerStart() {
        this.appHandler.onStartup(this);
    }

    /**
     * Inform this container that the server is being stopped.
     *
     * This method must be implicitly called before the server containing this container is stopped.
     */
    void onServerStop() {
        this.appHandler.onShutdown(this);
    }

    private static final class ResponseWriter implements ContainerResponseWriter {

        private final HttpExchange exchange;
        private final AtomicBoolean closed;

        /**
         * Creates a new ResponseWriter for given {@link HttpExchange HTTP Exchange}.
         *
         * @param exchange Exchange of the {@link HttpServer JDK Http Server}
         */
        ResponseWriter(final HttpExchange exchange) {
            this.exchange = exchange;
            this.closed = new AtomicBoolean(false);
        }

        @Override
        public OutputStream writeResponseStatusAndHeaders(final long contentLength, final ContainerResponse context)
                throws ContainerException {
            final MultivaluedMap<String, String> responseHeaders = context.getStringHeaders();
            final Headers serverHeaders = exchange.getResponseHeaders();
            for (final Map.Entry<String, List<String>> e : responseHeaders.entrySet()) {
                for (final String value : e.getValue()) {
                    serverHeaders.add(e.getKey(), value);
                }
            }

            try {
                if (context.getStatus() == Response.Status.NO_CONTENT.getStatusCode()) {
                    // Work around bug in LW HTTP server
                    // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6886436
                    exchange.sendResponseHeaders(context.getStatus(), -1);
                } else {
                    exchange.sendResponseHeaders(context.getStatus(),
                            getResponseLength(contentLength));
                }
            } catch (final IOException ioe) {
                throw new ContainerException(LocalizationMessages.ERROR_RESPONSEWRITER_WRITING_HEADERS(), ioe);
            }

            return exchange.getResponseBody();
        }

        private long getResponseLength(final long contentLength) {
            if (contentLength == 0) {
                return -1;
            }
            if (contentLength < 0) {
                return 0;
            }
            return contentLength;
        }

        @Override
        public boolean suspend(final long timeOut, final TimeUnit timeUnit, final TimeoutHandler timeoutHandler) {
            throw new UnsupportedOperationException("Method suspend is not supported by the container.");
        }

        @Override
        public void setSuspendTimeout(final long timeOut, final TimeUnit timeUnit) throws IllegalStateException {
            throw new UnsupportedOperationException("Method setSuspendTimeout is not supported by the container.");
        }

        @Override
        public void failure(final Throwable error) {
            try {
                exchange.sendResponseHeaders(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), getResponseLength(0));
            } catch (final IOException e) {
                LOGGER.log(Level.WARNING, LocalizationMessages.ERROR_RESPONSEWRITER_SENDING_FAILURE_RESPONSE(), e);
            } finally {
                commit();
                rethrow(error);
            }
        }

        @Override
        public boolean enableResponseBuffering() {
            return true;
        }

        @Override
        public void commit() {
            if (closed.compareAndSet(false, true)) {
                exchange.close();
            }
        }

        /**
         * Rethrow the original exception as required by JAX-RS, 3.3.4
         *
         * @param error throwable to be re-thrown
         */
        private void rethrow(final Throwable error) {
            if (error instanceof RuntimeException) {
                throw (RuntimeException) error;
            } else {
                throw new ContainerException(error);
            }
        }

        /**
         * Commits the response and logs a warning message.
         *
         * This method should be called by the container at the end of the
         * handle method to make sure that the ResponseWriter was committed.
         */
        private void closeAndLogWarning() {
            if (closed.compareAndSet(false, true)) {
                exchange.close();
                LOGGER.log(Level.WARNING, LocalizationMessages.ERROR_RESPONSEWRITER_RESPONSE_UNCOMMITED());
            }
        }
    }
}
