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

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.configuration.CommonProperties;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.logging.logback.LogbackLoggingSystemLauncherListener;
import org.apache.qpid.server.model.AbstractSystemConfig;
import org.apache.qpid.server.model.JsonSystemConfigImpl;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.plugin.ProtocolEngineCreator;
import org.apache.qpid.server.plugin.QpidServiceLoader;
import org.apache.qpid.server.util.FileUtils;
import org.apache.qpid.server.util.StringUtil;

/**
 * Main entry point for Apache Qpid Broker-J.
 *
 */
public class Main
{
    public static final String PROPERTY_QPID_HOME = "QPID_HOME";
    /**
     * Configuration property name for the absolute path to use for the broker home directory.
     *
     * If not otherwise set, the value for this configuration property defaults to the location
     * set in the "QPID_HOME" system property if that was set, or remains unset if it was not.
     */
    private static final String QPID_HOME_DIR  = "qpid.home_dir";

    private static final int MANAGEMENT_MODE_PASSWORD_LENGTH = 10;

    private static final Option OPTION_HELP = Option.builder("h")
                                                    .desc("print this message")
                                                    .longOpt("help")
                                                    .build();

    private static final Option OPTION_VERSION = Option.builder("v")
                                                       .desc("print the version information and exit")
                                                       .longOpt("version")
                                                       .build();

    private static final Option OPTION_CONFIGURATION_STORE_PATH = Option.builder("sp")
                                                                        .argName("path")
                                                                        .hasArg()
                                                                        .desc("use given configuration store location")
                                                                        .longOpt("store-path")
                                                                        .build();

    private static final Option OPTION_CONFIGURATION_STORE_TYPE = Option.builder("st")
                                                                        .argName("type")
                                                                        .hasArg()
                                                                        .desc("use given broker configuration store "
                                                                              + "type")
                                                                        .longOpt("store-type")
                                                                        .build();

    private static final Option OPTION_INITIAL_CONFIGURATION_PATH = Option.builder("icp")
                                                                          .argName("path")
                                                                          .hasArg()
                                                                          .desc("set the location of initial JSON "
                                                                                + "config to use when "
                                                                                + "creating/overwriting a broker "
                                                                                + "configuration store")
                                                                          .longOpt("initial-config-path")
                                                                          .build();

    private static final Option OPTION_CREATE_INITIAL_CONFIG = Option.builder("cic")
                                                                     .argName("path")
                                                                     .numberOfArgs(1)
                                                                     .optionalArg(true)
                                                                     .desc("create a copy of the initial config file,"
                                                                           + " either to an"
                                                                           +
                                                                           " optionally specified file path, or as "
                                                                           + SystemConfig.DEFAULT_INITIAL_CONFIG_NAME
                                                                           + " in the current directory")
                                                                     .longOpt("create-initial-config")
                                                                     .build();

    private static final Option OPTION_CONFIGURATION_PROPERTY = Option.builder("prop")
                                                                      .argName("name=value").hasArg()
                                                                      .desc("set a configuration property to use when"
                                                                            + " resolving variables in the broker "
                                                                            + "configuration store, with format "
                                                                            + "\"name=value\"")
                                                                      .longOpt("config-property")
                                                                      .build();

    private static final Option OPTION_MANAGEMENT_MODE = Option.builder("mm")
                                                               .desc("start broker in management mode, disabling the "
                                                                     + "AMQP ports")
                                                               .longOpt("management-mode")
                                                               .build();

    private static final Option OPTION_MM_QUIESCE_VHOST_NODE = Option.builder("mmqv")
                                                                     .desc("make virtual host nodes stay in the "
                                                                           + "quiesced state during management mode")
                                                                     .longOpt("management-mode-quiesce-virtualhostnodes")
                                                                     .build();

    private static final Option OPTION_MM_HTTP_PORT = Option.builder("mmhttp")
                                                            .argName("port")
                                                            .hasArg()
                                                            .desc("override http management port in management mode")
                                                            .longOpt("management-mode-http-port")
                                                            .build();

    private static final Option OPTION_MM_PASSWORD = Option.builder("mmpass")
                                                           .argName("password")
                                                           .hasArg()
                                                           .desc("set the password for the management mode user "
                                                                 + SystemConfig.MANAGEMENT_MODE_USER_NAME)
                                                           .longOpt("management-mode-password")
                                                           .build();

    private static final Option OPTION_INITIAL_SYSTEM_PROPERTIES = Option.builder("props")
                                                                         .argName("path")
                                                                         .hasArg()
                                                                         .desc("set the location of initial properties file to set otherwise unset system properties")
                                                                         .longOpt("system-properties-file")
                                                                         .build();

    private static final Options OPTIONS = new Options();

    static
    {
        OPTIONS.addOption(OPTION_HELP);
        OPTIONS.addOption(OPTION_VERSION);
        OPTIONS.addOption(OPTION_CONFIGURATION_STORE_PATH);
        OPTIONS.addOption(OPTION_CONFIGURATION_STORE_TYPE);
        OPTIONS.addOption(OPTION_CREATE_INITIAL_CONFIG);
        OPTIONS.addOption(OPTION_INITIAL_CONFIGURATION_PATH);
        OPTIONS.addOption(OPTION_MANAGEMENT_MODE);
        OPTIONS.addOption(OPTION_MM_QUIESCE_VHOST_NODE);
        OPTIONS.addOption(OPTION_MM_HTTP_PORT);
        OPTIONS.addOption(OPTION_MM_PASSWORD);
        OPTIONS.addOption(OPTION_CONFIGURATION_PROPERTY);
        OPTIONS.addOption(OPTION_INITIAL_SYSTEM_PROPERTIES);

        CommonProperties.ensureIsLoaded();
    }

    protected CommandLine _commandLine;

    public static void main(String[] args)
    {
        new Main(args);
    }

    public Main(final String[] args)
    {
        if (parseCommandline(args))
        {
            try
            {
                execute();
            }
            catch(Exception e)
            {
                System.err.println("Exception during startup: " + e);
                e.printStackTrace();
                shutdown(1);
            }
        }
    }

    protected boolean parseCommandline(final String[] args)
    {
        try
        {
            _commandLine = new DefaultParser().parse(OPTIONS, args);

            return true;
        }
        catch (ParseException e)
        {
            System.err.println("Error: " + e.getMessage());
            HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("Qpid", OPTIONS, true);

            return false;
        }
    }

    protected void execute() throws Exception
    {
        Map<String,Object> attributes = new HashMap<>();

        String initialProperties = _commandLine.getOptionValue(OPTION_INITIAL_SYSTEM_PROPERTIES.getOpt());
        SystemLauncher.populateSystemPropertiesFromDefaults(initialProperties);

        String initialConfigLocation = _commandLine.getOptionValue(OPTION_INITIAL_CONFIGURATION_PATH.getOpt());
        if(initialConfigLocation != null)
        {
            attributes.put(SystemConfig.INITIAL_CONFIGURATION_LOCATION, initialConfigLocation);
        }

        //process the remaining options
        if (_commandLine.hasOption(OPTION_HELP.getOpt()))
        {
            final HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("Qpid", OPTIONS, true);
        }
        else if (_commandLine.hasOption(OPTION_CREATE_INITIAL_CONFIG.getOpt()))
        {
            createInitialConfigCopy(initialConfigLocation);
        }
        else if (_commandLine.hasOption(OPTION_VERSION.getOpt()))
        {
            printVersion();
        }
        else
        {
            String[] configPropPairs = _commandLine.getOptionValues(OPTION_CONFIGURATION_PROPERTY.getOpt());

            Map<String, String> context = calculateConfigContext(configPropPairs);
            if(!context.isEmpty())
            {
                attributes.put(SystemConfig.CONTEXT, context);
            }

            String configurationStore = _commandLine.getOptionValue(OPTION_CONFIGURATION_STORE_PATH.getOpt());
            if(configurationStore != null)
            {
                attributes.put("storePath", configurationStore);
            }
            String configurationStoreType = _commandLine.getOptionValue(OPTION_CONFIGURATION_STORE_TYPE.getOpt());
            attributes.put(SystemConfig.TYPE, configurationStoreType == null ? JsonSystemConfigImpl.SYSTEM_CONFIG_TYPE : configurationStoreType);

            boolean managementMode = _commandLine.hasOption(OPTION_MANAGEMENT_MODE.getOpt());
            if (managementMode)
            {
                attributes.put(SystemConfig.MANAGEMENT_MODE, true);
                String httpPort = _commandLine.getOptionValue(OPTION_MM_HTTP_PORT.getOpt());
                if(httpPort != null)
                {
                    attributes.put(SystemConfig.MANAGEMENT_MODE_HTTP_PORT_OVERRIDE, httpPort);
                }

                boolean quiesceVhosts = _commandLine.hasOption(OPTION_MM_QUIESCE_VHOST_NODE.getOpt());
                attributes.put(SystemConfig.MANAGEMENT_MODE_QUIESCE_VIRTUAL_HOSTS, quiesceVhosts);

                String password = _commandLine.getOptionValue(OPTION_MM_PASSWORD.getOpt());
                if (password == null)
                {
                    password = new StringUtil().randomAlphaNumericString(MANAGEMENT_MODE_PASSWORD_LENGTH);
                }
                attributes.put(SystemConfig.MANAGEMENT_MODE_PASSWORD, password);
            }
            setExceptionHandler();

            startBroker(attributes);
        }
    }

    private Map<String, String> calculateConfigContext(final String[] configPropPairs)
    {
        Map<String,String> context = new HashMap<>();

        if(configPropPairs != null && configPropPairs.length > 0)
        {
            for(String s : configPropPairs)
            {
                int firstEquals = s.indexOf("=");
                if(firstEquals == -1)
                {
                    throw new IllegalArgumentException("Configuration property argument is not of the format name=value: " + s);
                }
                String name = s.substring(0, firstEquals);
                String value = s.substring(firstEquals + 1);

                if(name.equals(""))
                {
                    throw new IllegalArgumentException("Configuration property argument is not of the format name=value: " + s);
                }

                context.put(name, value);
            }
        }
        if(!context.containsKey(QPID_HOME_DIR))
        {
            Properties systemProperties = System.getProperties();
            final Map<String, String> environment = System.getenv();
            if(systemProperties.containsKey(QPID_HOME_DIR))
            {
                context.put(QPID_HOME_DIR, systemProperties.getProperty(QPID_HOME_DIR));
            }
            else if(environment.containsKey(QPID_HOME_DIR))
            {
                context.put(QPID_HOME_DIR, environment.get(QPID_HOME_DIR));
            }
            else if(context.containsKey(PROPERTY_QPID_HOME))
            {
                context.put(QPID_HOME_DIR, context.get(PROPERTY_QPID_HOME));
            }
            else if(systemProperties.containsKey(PROPERTY_QPID_HOME))
            {
                context.put(QPID_HOME_DIR, systemProperties.getProperty(PROPERTY_QPID_HOME));
            }
            else if(environment.containsKey(PROPERTY_QPID_HOME))
            {
                context.put(QPID_HOME_DIR, environment.get(PROPERTY_QPID_HOME));
            }
        }
        return context;
    }

    private void printVersion()
    {
        final StringBuilder protocol = new StringBuilder("AMQP version(s) [major.minor]: ");
        boolean first = true;
        Set<Protocol> protocols = new TreeSet<>();
        for(ProtocolEngineCreator installedEngine : (new QpidServiceLoader()).instancesOf(ProtocolEngineCreator.class))
        {
            protocols.add(installedEngine.getVersion());
        }
        for(Protocol supportedProtocol : protocols)
        {
            if (first)
            {
                first = false;
            }
            else
            {
                protocol.append(", ");
            }

            protocol.append(supportedProtocol.getProtocolVersion());
        }

        System.out.println(CommonProperties.getVersionString() + " (" + protocol + ")");
    }

    private void createInitialConfigCopy(String initialConfigLocation)
    {
        File destinationFile = null;

        String destinationOption = _commandLine.getOptionValue(OPTION_CREATE_INITIAL_CONFIG.getOpt());
        if (destinationOption != null)
        {
            destinationFile = new File(destinationOption);
        }
        else
        {
            destinationFile = new File(System.getProperty("user.dir"), SystemConfig.DEFAULT_INITIAL_CONFIG_NAME);
        }

        if(initialConfigLocation == null)
        {
            initialConfigLocation = AbstractSystemConfig.getDefaultValue(SystemConfig.INITIAL_CONFIGURATION_LOCATION);
        }
        copyInitialConfigFile(initialConfigLocation, destinationFile);

        System.out.println("Initial config written to: " + destinationFile.getAbsolutePath());
    }

    private void copyInitialConfigFile(final String initialConfigLocation, final File destinationFile)
    {
        URL url = null;
        try
        {
            url = new URL(initialConfigLocation);
        }
        catch (MalformedURLException e)
        {
            File locationFile = new File(initialConfigLocation);
            try
            {
                url = locationFile.toURI().toURL();
            }
            catch (MalformedURLException e1)
            {
                throw new IllegalConfigurationException("Cannot create URL for file " + locationFile, e1);
            }
        }
        InputStream in =  null;
        try
        {
            in = url.openStream();
            FileUtils.copy(in, destinationFile);
        }
        catch (IOException e)
        {
            throw new IllegalConfigurationException("Cannot create file " + destinationFile
                                                    + " by copying initial config from " + initialConfigLocation, e);
        }
        finally
        {
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (IOException e)
                {
                    throw new IllegalConfigurationException("Cannot close initial config input stream: " + initialConfigLocation, e);
                }
            }
        }
    }

    protected void setExceptionHandler()
    {
        Thread.UncaughtExceptionHandler handler = null;
        String handlerClass = System.getProperty("qpid.broker.exceptionHandler");
        if(handlerClass != null)
        {
            try
            {
                handler = (Thread.UncaughtExceptionHandler) Class.forName(handlerClass)
                        .getDeclaredConstructor().newInstance();
            }
            catch (ClassNotFoundException | InstantiationException | IllegalAccessException | ClassCastException |
                    NoSuchMethodException | InvocationTargetException e)
            {
                // ignore
            }
        }
        
        if(handler == null)
        {
            handler = (thread, exception) ->
            {
                boolean continueOnError = Boolean.getBoolean("qpid.broker.exceptionHandler.continue");
                try
                {
                    System.err.println("########################################################################");
                    System.err.println("#");
                    System.err.print("# Unhandled Exception ");
                    System.err.print(exception.toString());
                    System.err.print(" in Thread ");
                    System.err.println(thread.getName());
                    System.err.println("#");
                    System.err.println(continueOnError ? "# Forced to continue by JVM setting 'qpid.broker.exceptionHandler.continue'" : "# Exiting");
                    System.err.println("#");
                    System.err.println("########################################################################");
                    exception.printStackTrace(System.err);

                    Logger logger = LoggerFactory.getLogger("org.apache.qpid.server.Main");
                    logger.error("Uncaught exception, " + (continueOnError ? "continuing." : "shutting down."), exception);
                }
                finally
                {
                    if (!continueOnError)
                    {
                        Runtime.getRuntime().halt(1);
                    }
                }
            };

            Thread.setDefaultUncaughtExceptionHandler(handler);
        } 
    }

    protected void startBroker(Map<String,Object> attributes) throws Exception
    {
        SystemLauncher systemLauncher = new SystemLauncher(new LogbackLoggingSystemLauncherListener(),
                                                           new SystemLauncherListener.DefaultSystemLauncherListener()
                                                           {
                                                               @Override
                                                               public void onShutdown(final int exitCode)
                                                               {
                                                                   if (exitCode != 0)
                                                                   {
                                                                       shutdown(exitCode);
                                                                   }
                                                               }
                                                           });

        systemLauncher.startup(attributes);
    }

    protected void shutdown(final int status)
    {
        System.exit(status);
    }

}
