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

import static java.lang.String.format;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.apache.jena.fuseki.server.Operation.GSP_R;
import static org.apache.jena.fuseki.server.Operation.GSP_RW;
import static org.apache.jena.fuseki.server.Operation.Query;
import static org.apache.jena.fuseki.server.Operation.Update;
import static org.apache.jena.fuseki.servlets.ActionExecLib.allocHttpAction;

import java.util.Collection;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.jena.atlas.lib.InternalErrorException;
import org.apache.jena.fuseki.Fuseki;
import org.apache.jena.fuseki.auth.Auth;
import org.apache.jena.fuseki.servlets.*;
import org.apache.jena.fuseki.system.ActionCategory;
import org.apache.jena.riot.WebContent;
import org.apache.jena.riot.web.HttpNames;
import org.apache.jena.web.HttpSC;
import org.slf4j.Logger;

/**
 * Dispatch on registered datasets. This is the entry point into Fuseki for dataset
 * operations.
 *
 * Administration operations, and directly registered servlets and static content are
 * called through the usual web server process.
 *
 * HTTP Request URLs, after servlet context removed, take the form {@code /dataset} or {@code /dataset/service}.
 * The most general URL is {@code /context/dataset/service}.
 * The {@link DataAccessPointRegistry} maps {@code /dataset} to a {@link DataAccessPoint}.
 */
public class Dispatcher {

    // Development debugging only. Excessive for normal operation.
    private static final boolean LogDispatch = false;
    private static Logger        LOG         = Fuseki.serverLog;

    /**
     * Handle an HTTP request if it is sent to a registered dataset.
     *
     * Fuseki uses dynamic dispatch, the set of registered datasets can change while
     * the server is running, so dispatch is driven off Fuseki system registries.
     *
     * If the request URL matches a registered dataset, process the request, and send
     * the response.
     *
     * This function is called by {@link FusekiFilter#doFilter}.
     *
     * @param request
     *            HttpServletRequest
     * @param response
     *            HttpServletResponse
     * @return Returns {@code true} if the request has been handled, else false (no
     *         response sent).
     */
    public static boolean dispatch(HttpServletRequest request, HttpServletResponse response) {
        // Path component of the URI, without context path
        String uri = ActionLib.actionURI(request);
        String datasetUri = ActionLib.mapRequestToDataset(uri);

        if ( LogDispatch ) {
            LOG.info("Filter: Request URI = " + request.getRequestURI());
            LOG.info("Filter: Action URI  = " + uri);
            LOG.info("Filter: Dataset URI = " + datasetUri);
        }

        if ( datasetUri == null )
            return false;

        DataAccessPointRegistry registry = DataAccessPointRegistry.get(request.getServletContext());
        if ( !registry.isRegistered(datasetUri) ) {
            if ( LogDispatch )
                LOG.debug("No dispatch for '"+datasetUri+"'");
            return false;
        }
        DataAccessPoint dap = registry.get(datasetUri);
        return process(dap, request, response);
    }

    /** Set up and handle a HTTP request for a dataset. */
    private static boolean process(DataAccessPoint dap, HttpServletRequest request, HttpServletResponse response) {
        HttpAction action = allocHttpAction(dap, Fuseki.actionLog, ActionCategory.ACTION, request, response);
        return dispatchAction(action);
    }

    /**
     * Determine and call the {@link ActionProcessor} to handle this
     * {@link HttpAction}, including access control at the dataset and service levels.
     */
    public static boolean dispatchAction(HttpAction action) {
        return ActionExecLib.execAction(action, ()->chooseProcessor(action));
    }

    /**
     * Find the ActionProcessor or return null if there can't determine one.
     *
     * This function sends the appropriate HTTP error response.
     *
     * Returning null indicates an HTTP error response, and the HTTP response has been done.
     *
     * Process
     * <li> mapRequestToEndpointName -> endpoint name
     * <li> chooseEndpoint(action, dataService, endpointName) -> Endpoint.
     * <li> Endpoint to Operation (endpoint carries Operation).
     * <li> target(action, operation) -> ActionProcess.
     *
     * @param action
     * @return ActionProcessor or null if the request URI does not name a service or the dataset.
     *
     */
    private static ActionProcessor chooseProcessor(HttpAction action) {
        // "return null" indicates that processing failed to find a ActionProcessor
        DataAccessPoint dataAccessPoint = action.getDataAccessPoint();
        DataService dataService = action.getDataService();

        if ( !dataService.isAcceptingRequests() ) {
            ServletOps.error(HttpSC.SERVICE_UNAVAILABLE_503, "Dataset not currently active");
            return null;
        }

        // ---- Determine Endpoint.
        String endpointName = mapRequestToEndpointName(action, dataAccessPoint);

        Endpoint endpoint = chooseEndpoint(action, dataService, endpointName);
        if ( endpoint == null ) {
            if ( isEmpty(endpointName) )
                ServletOps.errorBadRequest("No operation for request: "+action.getActionURI());
            else {
                // No dispatch - the filter passes these through if the ActionProcessor is null.
                return null;
                // If this is used, resources (servlets, sttaic files) under "/dataset/" are not accessible.
                //ServletOps.errorNotFound("No endpoint: "+action.getActionURI());
            }
            return null;
        }

        Operation operation = endpoint.getOperation();
        if ( operation == null ) {
            ServletOps.errorNotFound("No operation: "+action.getActionURI());
            return null;
        }

        action.setEndpoint(endpoint);

        // ---- Authorization
        // -- Server-level authorization.
        // Checking was carried out by servlet filter AuthFilter.
        // Need to check Data service and endpoint authorization policies.
        String user = action.getUser();

        // -- Data service level authorization
        if ( dataService.authPolicy() != null ) {
            if ( ! dataService.authPolicy().isAllowed(user) )
                ServletOps.errorForbidden();
        }

        // -- Endpoint level authorization
        // Make sure all contribute authentication.
        Auth.allow(user, action.getEndpoint().getAuthPolicy(), ServletOps::errorForbidden);
        if ( isEmpty(endpointName) && ! endpoint.isUnnamed() ) {
            // [DISPATCH LEGACY]
            // If choice was by looking in all named endpoints for a unnamed endpoint
            // request, ensure all choices allow access.
            // There may be several endpoints for the operation.
            // Authorization is the AND of all endpoints.
            Collection<Endpoint> x = getEndpoints(dataService, operation);
            if ( x.isEmpty() )
                throw new InternalErrorException("Inconsistent: no endpoints for "+operation);
            x.forEach(ept->
                Auth.allow(user, ept.getAuthPolicy(), ServletOps::errorForbidden));
        }
        // ---- Authorization checking.

        // ---- Handler.
        // Decide the code to execute the request.
        ActionProcessor processor = endpoint.getProcessor();
        if ( processor == null )
            ServletOps.errorBadRequest(format("No processor: dataset=%s: op=%s", dataAccessPoint.getName(), operation.getName()));
        return processor;
    }

    /**
     * Map request to operation name.
     * Returns the service name (the part after the "/" of the dataset part) or "".
     */
    protected static String mapRequestToEndpointName(HttpAction action, DataAccessPoint dataAccessPoint) {
        return ActionLib.mapRequestToEndpointName(action, dataAccessPoint);
    }

    // Find the endpoints for an operation.
    // This is GSP_R/GSP_RW aware.
    // If asked for GSP_R and there are no endpoints for GSP_R, try GSP_RW.
    private static Collection<Endpoint> getEndpoints(DataService dataService, Operation operation) {
        Collection<Endpoint> x = dataService.getEndpoints(operation);
        if ( x == null || x.isEmpty() ) {
            if ( operation == GSP_R )
                x = dataService.getEndpoints(GSP_RW);
        }
        return x;
    }

    /**
     * Choose an endpoint. This can be with or without endpointName.
     * If there is no endpoint and the action is on the data service itself (unnamed endpoint)
     * look for a named endpoint that supplies the operation.
     */
    private static Endpoint chooseEndpoint(HttpAction action, DataService dataService, String endpointName) {
        try {
            Endpoint ep = chooseEndpointNoLegacy(action, dataService, endpointName);
            if ( ep != null )
                return ep;
            // No dispatch so far.

            if ( ! isEmpty(endpointName) )
                return ep;
            // [DISPATCH LEGACY]

            // When it is a unnamed service request (operation on the dataset) and there
            // is no match, search the named services.
            Operation operation = chooseOperation(action);
            // Search for an endpoint that provides the operation.
            // No guarantee it has the access controls for the operation
            // but in this case, access control will validate against all possible endpoints.
            ep = findEndpointForOperation(action, dataService, operation, true);
            return ep;
        } catch (ActionErrorException ex) {
            throw ex;
        } catch (RuntimeException ex) {
            // Example: Jetty throws BadMessageException when it is an HTML form and it is too big.
            ServletOps.errorBadRequest(ex.getMessage());
            return null;
        }
    }

    /**
     * Choose an endpoint.
     * <ul>
     * <li>Look by service name to get the EndpointSet</li>
     * <li>If empty set, return null.</li>
     * <li>If there is only one choice, return that (may even be the wrong operation
     *       - processor implmentations must be defensive).</li>
     * <li>If multiple choices, classify the operation
     *     (includes custom content-type) and look up by operation.</li>
     * <li>Return a match wit a r
     * </ul>
     */
    private static Endpoint chooseEndpointNoLegacy(HttpAction action, DataService dataService, String endpointName) {
        EndpointSet epSet = isEmpty(endpointName) ? dataService.getEndpointSet() : dataService.getEndpointSet(endpointName);

        if ( epSet == null || epSet.isEmpty() )
            // No matches by name.
            return null;

        // If there is one endpoint, dispatch there directly.
        Endpoint ep = epSet.getExactlyOne();
        if ( ep != null )
            return ep;
        // No single direct dispatch. Multiple choices (different operation, same endpoint name)
        // Work out which operation we are looking for.
        Operation operation = chooseOperation(action);
        ep = epSet.get(operation);
        // This also happens in findEndpointForOperation
        // If a GSP-R request, try for GSP-RW
        if ( ep == null && Operation.GSP_R.equals(operation) )
            ep = epSet.get(Operation.GSP_RW);
        return ep;
    }

    /**
     *  Find an endpoint for an operation.
     *  This searches all endpoints of a {@link DataService} that provide the {@link Operation}.
     *  This understands that GSP_RW can service GSP_R.
     *  Used for legacy dispatch.
     */
    private static Endpoint findEndpointForOperation(HttpAction action, DataService dataService, Operation operation, boolean preferUnnamed) {
        Endpoint ep = findEndpointForOperationExact(dataService, operation, preferUnnamed);
        if ( ep != null )
            return ep;
        // Try to find "R" functionality from an RW.
        if ( GSP_R.equals(operation) )
            return findEndpointForOperationExact(dataService, GSP_RW, preferUnnamed);
        // Instead of 404, return 405 if asked for RW but only R available.
        if ( GSP_RW.equals(operation) && dataService.hasOperation(GSP_R) )
            ServletOps.errorMethodNotAllowed(action.getMethod());
        return null;
    }

    /** Find a matching endpoint for exactly this operation.
     * If multiple choices, prefer either named or unnamed according
     * to the flag {@code preferUnnamed}.
     */
    private static Endpoint findEndpointForOperationExact(DataService dataService, Operation operation, boolean preferUnnamed) {
        List<Endpoint> eps = dataService.getEndpoints(operation);
        if ( eps == null || eps.isEmpty() )
            return null;
        // ==== Legacy compatibility.
        // Find a named service, with preference for named/unnamed.
        Endpoint epAlt = null;
        for ( Endpoint ep : eps ) {
            if ( operation.equals(ep.getOperation()) ) {
                if ( ep.isUnnamed() && preferUnnamed )
                    return ep;
                if ( ! ep.isUnnamed() && ! preferUnnamed )
                    return ep;
                epAlt = ep;
            }
        }
        // Did not find a preferred one.
        return epAlt;
    }

    /**
     * Identify the operation being requested.
     * It is analysing the HTTP request using global configuration.
     * The decision is based on
     * <ul>
     * <li>Query parameters (URL query string or HTML form)</li>
     * <li>Content-Type header</li>
     * <li>Otherwise it is a plain REST (quads) operation.chooseOperation</li>
     * </ul>
     * The HTTP Method is not considered.
     * <p>
     * The operation is not guaranteed to be supported on every {@link DataService}
     * nor that access control will allow it to be performed.
     */
    public static Operation chooseOperation(HttpAction action) {
        HttpServletRequest request = action.getRequest();

        // ---- Dispatch based on HttpParams : Query, Update, GSP.
        // -- Query
        boolean isQuery = request.getParameter(HttpNames.paramQuery) != null;
        if ( isQuery )
            return Query;

        // -- Update
        // Standards name "update", non-standard name "request" (old use by Fuseki)
        boolean isUpdate = request.getParameter(HttpNames.paramUpdate) != null || request.getParameter(HttpNames.paramRequest) != null;
        if ( isUpdate )
            // The SPARQL_Update servlet will deal with using GET.
            return Update;

        // ---- Content-type
        // This does not have the ";charset="
        String ct = request.getContentType();
        if ( ct != null ) {
            Operation operation = action.getOperationRegistry().findByContentType(ct);
            if ( operation != null )
                return operation;
        }
        // We don't wire in all the RDF syntaxes.
        // Instead, "Quads" drops through to the default operation.

        // -- SPARQL Graph Store Protocol
        boolean hasParamGraph = request.getParameter(HttpNames.paramGraph) != null;
        boolean hasParamGraphDefault = request.getParameter(HttpNames.paramGraphDefault) != null;
        if ( hasParamGraph || hasParamGraphDefault )
            return gspOperation(action, request);

        // -- Any other queryString
        // Query string now unexpected.

        // Place for an extension point.
        boolean hasParams = request.getParameterMap().size() > 0;
        if ( hasParams ) {
            // One nasty case:
            // Bad HTML form (content-type  application/x-www-form-urlencoded), but body is not an HTML form.
            //  map is one entry, and the key is all of the body,
            if ( WebContent.contentTypeHTMLForm.equals(request.getContentType()) ) {
                ServletOps.errorBadRequest("Malformed request: unrecognized HTML form request");
                return null;
            }
            // Unrecognized ?key=value
            String qs = request.getQueryString();
            if ( qs != null )
                ServletOps.errorBadRequest("Malformed request: unrecognized parameters: " + qs);
            else
                ServletOps.errorBadRequest(HttpSC.getMessage(HttpSC.BAD_REQUEST_400));
        }


        // ---- No registered content type, no query parameters.
        // Plain HTTP operation on the dataset handled as quads or rejected.
        return quadsOperation(action, request);
    }

    /**
     * Determine the {@link Operation} for a SPARQL Graph Store Protocol (GSP) action.
     * <p>
     * Assumes, and does not check, that the action is a GSP action.
     *
     * @throws ActionErrorException
     *             (which causes a servlet 4xx response) if the operaton is not permitted.
     */
    private static Operation gspOperation(HttpAction action, HttpServletRequest request) throws ActionErrorException {
        // Check enabled.
        if ( isReadMethod(request) )
            return GSP_R;
        else
            return GSP_RW;
    }

    /**
     * Determine the {@link Operation} for a Quads operation. (GSP, except on the
     * whole dataset).
     * <p>
     * Assumes, and does not check, that the action is a Quads action.
     *
     * @throws ActionErrorException
     *             (which causes a servlet 405 response) if the operaton is not permitted.
     */
    private static Operation quadsOperation(HttpAction action, HttpServletRequest request) throws ActionErrorException {
        // Check enabled. Extends GSP.
        if ( isReadMethod(request) )
            return GSP_R;
        else
            return GSP_RW;
    }

    private static boolean isReadMethod(HttpServletRequest request) {
        String method = request.getMethod();
        // REST dataset.
        boolean isGET = method.equals(HttpNames.METHOD_GET);
        boolean isHEAD = method.equals(HttpNames.METHOD_HEAD);
        return isGET || isHEAD;
    }
}
