/*
 * 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.embedded;

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

import javax.servlet.ServletContext ;

import org.apache.jena.fuseki.Fuseki ;
import org.apache.jena.fuseki.FusekiConfigException ;
import org.apache.jena.fuseki.FusekiException ;
import org.apache.jena.fuseki.build.FusekiBuilder ;
import org.apache.jena.fuseki.build.FusekiConfig ;
import org.apache.jena.fuseki.jetty.FusekiErrorHandler1 ;
import org.apache.jena.fuseki.mgt.ActionStats ;
import org.apache.jena.fuseki.server.DataAccessPoint ;
import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
import org.apache.jena.fuseki.server.DataService ;
import org.apache.jena.fuseki.server.OperationName ;
import org.apache.jena.fuseki.servlets.FusekiFilter ;
import org.apache.jena.query.Dataset ;
import org.apache.jena.sparql.core.DatasetGraph ;
import org.eclipse.jetty.server.HttpConnectionFactory ;
import org.eclipse.jetty.server.Server ;
import org.eclipse.jetty.server.ServerConnector ;
import org.eclipse.jetty.servlet.FilterHolder ;
import org.eclipse.jetty.servlet.ServletContextHandler ;

/**
 * Embedded Fuseki server. This is a Fuseki server running with a precofigured set of
 * datasets and services. 
 * There is no admin UI.
 * <p>
 * To create a embedded sever, use {@link FusekiEmbeddedServer} ({@link #make} is a
 * packaging of a call to {@link FusekiEmbeddedServer} for the case of one dataset,
 * responding to localhost only).
 * <p>
 * The application should call {@link #start()} to actually start the server
 * (it wil run in the background : see {@link #join}).
 * <p>Example:
 * <pre>
 *      DatasetGraph dsg = ... ;
 *      FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
 *          .setPort(1234)
 *          .add("/ds", dsg)
 *          .build() ;
 *       server.start() ;
 * </pre>
 * Compact form (use the builder pattern above to get more flexibility):
 * <pre>
 *    FusekiEmbeddedServer.make(1234, "/ds", dsg).start() ;
 * </pre>
 * 
 */
public class FusekiEmbeddedServer {
    static { 
        //FusekiEnv.mode = FusekiEnv.INIT.EMBEDDED ;
        // Stop anything accidently resetting Fuseki server logging. 
        //FusekiLogging.allowLoggingReset(false) ;
    }
    
    /** Construct a Fuseki server for one dataset.
     * It only responds to localhost. 
     * The returned server has not been started  */ 
    static public FusekiEmbeddedServer make(int port, String name, DatasetGraph dsg) {
        return create()
            .setPort(port)
            .setLoopback(true)
            .add(name, dsg)
            .build() ;
    }
    
    public static Builder create() {
        return new Builder() ;
    }
    
    public final Server server ;
    private int port ;
    
    public FusekiEmbeddedServer(Server server) {
        this.server = server ;
        port = ((ServerConnector)server.getConnectors()[0]).getPort() ;
    }
    
    /** Get the underlying Jetty server which has also been set up. */ 
    public Server getJettyServer() {
        return server ; 
    }
    
    /** Get the {@link ServletContext}.
     * Adding new servlets is possible with care.
     */ 
    public ServletContext getServletContext() {
        return ((ServletContextHandler)server.getHandler()).getServletContext() ;
    }

    /** Start the server - the server continues to run after this call returns.
     *  To synchronise with the server stopping, call {@link #join}.  
     */
    public void start() { 
        try { server.start(); }
        catch (Exception e) { throw new FusekiException(e) ; }
        if ( port == 0 )
            port = ((ServerConnector)server.getConnectors()[0]).getLocalPort() ;
        Fuseki.serverLog.info("Start Fuseki (port="+port+")");
    }

    /** Stop the server. */
    public void stop() { 
        Fuseki.serverLog.info("Stop Fuseki (port="+port+")");
        try { server.stop(); }
        catch (Exception e) { throw new FusekiException(e) ; }
    }
    
    /** Wait for the server to exit. This call is blocking. */
    public void join() {
        try { server.join(); }
        catch (Exception e) { throw new FusekiException(e) ; }
    }
    
    /** FusekiEmbeddedServer.Builder */
    public static class Builder {
        // Keeping this allows accumulation of data access points for one name.  
        private Map<String, DataService> map = new HashMap<>() ;
        private int port = 3330 ;
        private boolean loopback = false ;
        private boolean withStats = false ;
        private String contextPath = "/" ;
        
        /* Set the port to run on */ 
        public Builder setPort(int port) {
            this.port = port ;
            return this ;
        }
        
        /* Context path to Fuseki.  If it's "/" then Fuseki URL look like
         * "http://host:port/dataset/query" else "http://host:port/path/dataset/query" 
         */
        public Builder setContextPath(String path) {
            this.contextPath = path ;
            return this ;
        }
        
        /** Restrict the server to only respoding to the localhost interface. */ 
        public Builder setLoopback(boolean loopback) {
            this.loopback = loopback;
            return this ;
        }

        /** Add the "/$/stats" servlet that responds with stats about the server,
         * including counts of all calls made.
         */ 
        public Builder enableStats(boolean withStats) {
            this.withStats = withStats;
            return this ;
        }

        /* Add the dataset with given name and a default set of services including update */  
        public Builder add(String name, Dataset ds) {
            return add(name, ds.asDatasetGraph()) ;
        }

        /* Add the dataset with given name and a default set of services including update */  
        public Builder add(String name, DatasetGraph dsg) {
            return add(name, dsg, true) ;
        }

        /* Add the dataset with given name and a default set of services. */  
        public Builder add(String name, Dataset ds, boolean allowUpdate) {
            return add(name, ds.asDatasetGraph(), allowUpdate) ;
        }
            
        
        /* Add the dataset with given name and a default set of services. */  
        public Builder add(String name, DatasetGraph dsg, boolean allowUpdate) {
            DataService dSrv = FusekiBuilder.buildDataService(dsg, allowUpdate) ; 
            return add(name, dSrv) ;
        }
        
        /* Add a data service that includes dataset and service names.*/  
        public Builder add(String name, DataService dataService) {
            return add$(name, dataService) ; 
        }
        
        /* Add an operation, specifing it's endpoint name.
         * This adds endpoints to any existing data service already setup by the builder.   
         */
        public Builder add(String name, Dataset ds, OperationName opName, String epName) {
            return add(name, ds.asDatasetGraph(), opName, epName) ; 
        }

            /* Add an operation, specifing it's endpoint name.
         * This adds endpoints to any existing data service already setup by the builder.   
         */
        public Builder add(String name, DatasetGraph dsg, OperationName opName, String epName) {
            DataService dSrv = map.get(name) ;
            if ( dSrv == null ) {
                dSrv = new DataService(dsg) ;
                map.put(name, dSrv) ;
            }
            dSrv.addEndpoint(opName, epName);
            return this ; 
        }

        private Builder add$(String name, DataService dataService) {
            name = DataAccessPoint.canonical(name) ;
            if ( map.containsKey(name) )
                throw new FusekiConfigException("Attempt to add a DataService for a different dataset: "+name) ;
            map.put(name, dataService) ;
            
            // Merge endpoints : too complicated 
//            DataService dSrv = map.get(name) ;
//            if ( dSrv != null ) {
//                DatasetGraph dsg1 = dSrv.getDataset() ;
//                DatasetGraph dsg2 = dataService.getDataset() ;
//                if ( dsg1 != dsg2 ) // Object identity
//                    throw new FusekiConfigException("Attempt to add a DataService for a different dataset: "+name) ;
//                dSrv.getOperations() ;
//            } else
//                map.put(name, dataService) ;
            return this ;
        }
        
        /** Read and parse a Fuseki services/datasets file.
         *  <p>
         *  The application is responsible for ensuring a correct classpath. For example,
         *  including a dependency on {@code jena-text} if the configuration file
         *  includes a text index.     
         */
        public Builder parseConfigFile(String filename) {
            List<DataAccessPoint> x = FusekiConfig.readConfigurationFile(filename) ;
            // Unbundle so that they accumulate.
            x.forEach(dap-> add(dap.getName(), dap.getDataService())) ;
            return this ;
        }

        /** Build a server according to the current description */ 
        public FusekiEmbeddedServer build() {
            DataAccessPointRegistry registry = new DataAccessPointRegistry() ;
            map.forEach((name, dSrv) -> {
                DataAccessPoint dap = new DataAccessPoint(name, dSrv) ;
                registry.put(name, dap) ;
            }) ;
            ServletContextHandler handler = buildServletContext(contextPath, registry) ;
            if ( withStats )
                handler.addServlet(ActionStats.class, "/$/stats") ;
            DataAccessPointRegistry.set(handler.getServletContext(), registry) ;
            Server server = jettyServer(port, loopback) ;
            server.setHandler(handler);
            return new FusekiEmbeddedServer(server) ;
        }

        /** Build a ServletContextHandler with the Fuseki router : {@link FusekiFilter} */
        private static ServletContextHandler buildServletContext(String contextPath, DataAccessPointRegistry registry) {
            if ( contextPath == null || contextPath.isEmpty() )
                contextPath = "/" ;
            else if ( !contextPath.startsWith("/") )
                contextPath = "/" + contextPath ;
            ServletContextHandler context = new ServletContextHandler() ;
            FusekiFilter ff = new FusekiFilter() ;
            FilterHolder h = new FilterHolder(ff) ;
            context.setContextPath(contextPath) ;
            context.addFilter(h, "/*", null) ;
            context.setDisplayName(Fuseki.servletRequestLogName) ;
            context.setErrorHandler(new FusekiErrorHandler1()) ;
            return context ;
        }
        
        /** Jetty server */
        private static Server jettyServer(int port, boolean loopback) {
            Server server = new Server() ;
            HttpConnectionFactory f1 = new HttpConnectionFactory() ;
            // Some people do try very large operations ... really, should use POST.
            f1.getHttpConfiguration().setRequestHeaderSize(512 * 1024);
            f1.getHttpConfiguration().setOutputBufferSize(5 * 1024 * 1024) ;
            // Do not add "Server: Jetty(....) when not a development system.
            if ( ! Fuseki.outputJettyServerHeader )
                f1.getHttpConfiguration().setSendServerVersion(false) ;
            ServerConnector connector = new ServerConnector(server, f1) ;
            connector.setPort(port) ;
            server.addConnector(connector);
            if ( loopback )
                connector.setHost("localhost");
            return server ;
        }
    }
}