/*
 * 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.storm.daemon.drpc;

import com.codahale.metrics.Meter;
import com.google.common.annotations.VisibleForTesting;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.apache.storm.Config;
import org.apache.storm.DaemonConfig;
import org.apache.storm.daemon.drpc.webapp.DRPCApplication;
import org.apache.storm.daemon.drpc.webapp.ReqContextFilter;
import org.apache.storm.daemon.ui.FilterConfiguration;
import org.apache.storm.daemon.ui.UIHelpers;
import org.apache.storm.generated.DistributedRPC;
import org.apache.storm.generated.DistributedRPCInvocations;
import org.apache.storm.metric.StormMetricsRegistry;
import org.apache.storm.security.auth.IHttpCredentialsPlugin;
import org.apache.storm.security.auth.ServerAuthUtils;
import org.apache.storm.security.auth.ThriftConnectionType;
import org.apache.storm.security.auth.ThriftServer;
import org.apache.storm.utils.ConfigUtils;
import org.apache.storm.utils.ObjectReader;
import org.apache.storm.utils.Utils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.servlet.ServletContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
public class DRPCServer implements AutoCloseable {
    private static final Logger LOG = LoggerFactory.getLogger(DRPCServer.class);
    private final Meter meterShutdownCalls;
   
    //TODO in the future this might be better in a common webapp location

    /**
     * Add a request context filter to the Servlet Context Handler.
     * @param context The Servlet Context handler
     * @param configName Config name
     * @param conf Conf to be added in context filter
     */
    public static void addRequestContextFilter(ServletContextHandler context, String configName, Map<String, Object> conf) {
        IHttpCredentialsPlugin auth = ServerAuthUtils.getHttpCredentialsPlugin(conf, (String)conf.get(configName));
        ReqContextFilter filter = new ReqContextFilter(auth);
        context.addFilter(new FilterHolder(filter), "/*", EnumSet.allOf(DispatcherType.class));
    }
 
    private static ThriftServer mkHandlerServer(final DistributedRPC.Iface service, Integer port, Map<String, Object> conf) {
        ThriftServer ret = null;
        if (port != null && port >= 0) {
            ret = new ThriftServer(conf, new DistributedRPC.Processor<>(service),
                    ThriftConnectionType.DRPC);
        }
        return ret;
    }

    private static ThriftServer mkInvokeServer(final DistributedRPCInvocations.Iface service, int port, Map<String, Object> conf) {
        return new ThriftServer(conf, new DistributedRPCInvocations.Processor<>(service),
                ThriftConnectionType.DRPC_INVOCATIONS);
    }
    
    private static Server mkHttpServer(StormMetricsRegistry metricsRegistry, Map<String, Object> conf, DRPC drpc) {
        Integer drpcHttpPort = (Integer) conf.get(DaemonConfig.DRPC_HTTP_PORT);
        Server ret = null;
        if (drpcHttpPort != null && drpcHttpPort >= 0) {
            LOG.info("Starting RPC HTTP servers...");
            String filterClass = (String) (conf.get(DaemonConfig.DRPC_HTTP_FILTER));
            @SuppressWarnings("unchecked")
            Map<String, String> filterParams = (Map<String, String>) (conf.get(DaemonConfig.DRPC_HTTP_FILTER_PARAMS));
            FilterConfiguration filterConfiguration = new FilterConfiguration(filterClass, filterParams);
            final List<FilterConfiguration> filterConfigurations = Arrays.asList(filterConfiguration);
            final Integer httpsPort = ObjectReader.getInt(conf.get(DaemonConfig.DRPC_HTTPS_PORT), 0);
            final String httpsKsPath = (String) (conf.get(DaemonConfig.DRPC_HTTPS_KEYSTORE_PATH));
            final String httpsKsPassword = (String) (conf.get(DaemonConfig.DRPC_HTTPS_KEYSTORE_PASSWORD));
            final String httpsKsType = (String) (conf.get(DaemonConfig.DRPC_HTTPS_KEYSTORE_TYPE));
            final String httpsKeyPassword = (String) (conf.get(DaemonConfig.DRPC_HTTPS_KEY_PASSWORD));
            final String httpsTsPath = (String) (conf.get(DaemonConfig.DRPC_HTTPS_TRUSTSTORE_PATH));
            final String httpsTsPassword = (String) (conf.get(DaemonConfig.DRPC_HTTPS_TRUSTSTORE_PASSWORD));
            final String httpsTsType = (String) (conf.get(DaemonConfig.DRPC_HTTPS_TRUSTSTORE_TYPE));
            final Boolean httpsWantClientAuth = (Boolean) (conf.get(DaemonConfig.DRPC_HTTPS_WANT_CLIENT_AUTH));
            final Boolean httpsNeedClientAuth = (Boolean) (conf.get(DaemonConfig.DRPC_HTTPS_NEED_CLIENT_AUTH));
            final Boolean disableHttpBinding = (Boolean) (conf.get(DaemonConfig.DRPC_DISABLE_HTTP_BINDING));

            //TODO a better way to do this would be great.
            DRPCApplication.setup(drpc, metricsRegistry);
            ret = UIHelpers.jettyCreateServer(drpcHttpPort, null, httpsPort, disableHttpBinding);
            
            UIHelpers.configSsl(ret, httpsPort, httpsKsPath, httpsKsPassword, httpsKsType, httpsKeyPassword,
                    httpsTsPath, httpsTsPassword, httpsTsType, httpsNeedClientAuth, httpsWantClientAuth);
            
            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
            context.setContextPath("/");
            ret.setHandler(context);

            ServletHolder jerseyServlet = context.addServlet(ServletContainer.class, "/*");
            jerseyServlet.setInitOrder(1);
            jerseyServlet.setInitParameter("javax.ws.rs.Application", DRPCApplication.class.getName());
            
            UIHelpers.configFilters(context, filterConfigurations);
            addRequestContextFilter(context, DaemonConfig.DRPC_HTTP_CREDS_PLUGIN, conf);
        }
        return ret;
    }
    
    private final DRPC drpc;
    private final ThriftServer handlerServer;
    private final ThriftServer invokeServer;
    private final Server httpServer;
    private Thread handlerServerThread;
    private boolean closed = false;

    /**
     * Constructor.
     * @param conf Drpc conf for the servers
     * @param metricsRegistry The metrics registry
     */
    public DRPCServer(Map<String, Object> conf, StormMetricsRegistry metricsRegistry) {
        meterShutdownCalls = metricsRegistry.registerMeter("drpc:num-shutdown-calls");
        drpc = new DRPC(metricsRegistry, conf);
        DRPCThrift thrift = new DRPCThrift(drpc);
        handlerServer = mkHandlerServer(thrift, ObjectReader.getInt(conf.get(Config.DRPC_PORT), null), conf);
        invokeServer = mkInvokeServer(thrift, ObjectReader.getInt(conf.get(Config.DRPC_INVOCATIONS_PORT), 3773), conf);
        httpServer = mkHttpServer(metricsRegistry, conf, drpc);
    }

    @VisibleForTesting
    void start() throws Exception {
        LOG.info("Starting Distributed RPC servers...");
        new Thread(invokeServer::serve).start();
        if (httpServer != null) {
            httpServer.start();
        }
        
        if (handlerServer != null) {
            handlerServerThread = new Thread(handlerServer::serve);
            handlerServerThread.start();
        }
    }
    
    @VisibleForTesting
    void awaitTermination() throws InterruptedException {
        if (handlerServerThread != null) {
            handlerServerThread.join();
        } else {
            httpServer.join();
        }
    }

    @Override
    public synchronized void close() {
        if (!closed) {
            if (handlerServer != null) {
                handlerServer.stop();
            }

            if (invokeServer != null) {
                invokeServer.stop();
            }

            //TODO this is causing issues...
            //if (httpServer != null) {
            //    httpServer.destroy();
            //}
            
            drpc.close();
            closed = true;
        }
    }

    /**
     * The port the DRPC handler server is listening on.
     * @return The port the DRPC handler server is listening on.
     */
    public int getDrpcPort() {
        return handlerServer.getPort();
    }

    /**
     * The port the DRPC invoke server is listening on.
     * @return The port the DRPC invoke server is listening on.
     */
    public int getDrpcInvokePort() {
        return invokeServer.getPort();
    }

    /**
     * The port the HTTP server is listening on. Not available until {@link #start() } has run.
     * @return The port the HTTP server is listening on. Not available until {@link #start() } has run.
     */
    public int getHttpServerPort() {
        assert httpServer.getConnectors().length == 1;
        
        return ((ServerConnector) (httpServer.getConnectors()[0])).getLocalPort();
    }

    /**
     * Main method to start the server.
     */
    public static void main(String [] args) throws Exception {
        Utils.setupDefaultUncaughtExceptionHandler();
        Map<String, Object> conf = ConfigUtils.readStormConfig();
        StormMetricsRegistry metricsRegistry = new StormMetricsRegistry();
        try (DRPCServer server = new DRPCServer(conf, metricsRegistry)) {
            metricsRegistry.startMetricsReporters(conf);
            Utils.addShutdownHookWithForceKillIn1Sec(() -> {
                server.meterShutdownCalls.mark();
                metricsRegistry.stopMetricsReporters();
                server.close();
            });
            server.start();
            server.awaitTermination();
        }
    }
}
