/*******************************************************************************
 * 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.ofbiz.base.start;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.ofbiz.base.start.Start.ServerState;

/**
 * The StartupControlPanel controls OFBiz by executing high level
 * functions such as init, start and stop on the server. The bulk
 * of the startup sequence logic resides in this class.
 */
final class StartupControlPanel {

    /**
     * Initialize OFBiz by:
     * - setting high level JVM and OFBiz system properties
     * - creating a Config object holding startup configuration parameters
     *
     * @param ofbizCommands: commands passed by the user to OFBiz on start
     * @return config: OFBiz configuration
     */
    static Config init(List<StartupCommand> ofbizCommands) {
        Config config = null;
        try {
            loadGlobalOfbizSystemProperties("ofbiz.system.props");
            config =  new Config(ofbizCommands);
        } catch (StartupException e) {
            fullyTerminateSystem(e);
        }
        return config;
    }

    /**
     * Execute the startup sequence for OFBiz
     */
    static void start(Config config,
            AtomicReference<ServerState> serverState,
            List<StartupCommand> ofbizCommands) throws StartupException {

        List<StartupLoader> loaders = new ArrayList<StartupLoader>();
        Thread adminServer = createAdminServer(config, serverState, loaders);
        Classpath classPath = createClassPath(config);
        NativeLibClassLoader classLoader = createAndSetContextClassLoader(config, classPath);

        createLogDirectoryIfMissing(config);
        createRuntimeShutdownHook(config, loaders, serverState);
        loadStartupLoaders(config, loaders, ofbizCommands, serverState, classLoader);
        executeShutdownAfterLoadIfConfigured(config, loaders, serverState, adminServer);
    }

    /**
     * Shutdown the OFBiz server. This method is invoked in one of the
     * following ways:
     *
     * - Manually if requested by the client AdminClient
     * - Automatically if Config.shutdownAfterLoad is set to true
     */
    static void stop(List<StartupLoader> loaders, AtomicReference<ServerState> serverState, Thread adminServer) {
        shutdownServer(loaders, serverState, adminServer);
        System.exit(0);
    }

    /**
     * Properly exit from the system when a StartupException cannot or
     * should not be handled except by exiting the system.
     *
     * A proper system exit is achieved by:
     *
     * - Printing the stack trace for users to see what happened
     * - Executing the shutdown hooks (if existing) through System.exit
     * - Terminating any lingering threads (if existing) through System.exit
     * - Providing an exit code that is not 0 to signal to the build system 
     *   or user of failure to execute.
     * 
     * @param e: The startup exception that cannot / should not be handled
     *   except by terminating the system
     */
    static void fullyTerminateSystem(StartupException e) {
        e.printStackTrace();
        System.exit(1);
    }

    private static void shutdownServer(List<StartupLoader> loaders, AtomicReference<ServerState> serverState, Thread adminServer) {
        ServerState currentState;
        do {
            currentState = serverState.get();
            if (currentState == ServerState.STOPPING) {
                return;
            }
        } while (!serverState.compareAndSet(currentState, ServerState.STOPPING));
        // The current thread was the one that successfully changed the state;
        // continue with further processing.
        synchronized (loaders) {
            // Unload in reverse order
            for (int i = loaders.size(); i > 0; i--) {
                StartupLoader loader = loaders.get(i - 1);
                try {
                    loader.unload();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        if (adminServer != null && adminServer.isAlive()) {
            adminServer.interrupt();
        }
    }

    private static void loadGlobalOfbizSystemProperties(String globalOfbizPropertiesFileName) throws StartupException {
        String systemProperties = System.getProperty(globalOfbizPropertiesFileName);
        if (systemProperties != null) {
            FileInputStream stream = null;
            try {
                stream = new FileInputStream(systemProperties);
                System.getProperties().load(stream);
                stream.close();
            } catch (IOException e) {
                throw new StartupException("Couldn't load global system props", e);
            }
        }
    }

    private static Thread createAdminServer(
            Config config,
            AtomicReference<ServerState> serverState,
            List<StartupLoader> loaders) throws StartupException {

        Thread adminServer = null;
        if (config.adminPort > 0) {
            adminServer = new AdminServer(loaders, serverState, config);
            adminServer.start();
        } else {
            System.out.println("Admin socket not configured; set to port 0");
        }
        return adminServer;
    }

    private static Classpath createClassPath(Config config) throws StartupException {
        Classpath classPath = new Classpath();
        try {
            classPath.addComponent(config.ofbizHome);
            String ofbizHomeTmp = config.ofbizHome;
            if (!ofbizHomeTmp.isEmpty() && !ofbizHomeTmp.endsWith("/")) {
                ofbizHomeTmp = ofbizHomeTmp.concat("/");
            }
            if (config.classpathAddComponent != null) {
                String[] components = config.classpathAddComponent.split(",");
                for (String component : components) {
                    classPath.addComponent(ofbizHomeTmp.concat(component.trim()));
                }
            }
        } catch (IOException e) {
            throw new StartupException("Cannot create classpath", e);
        }
        return classPath;
    }

    private static NativeLibClassLoader createAndSetContextClassLoader(Config config, Classpath classPath) throws StartupException {
        ClassLoader parent = Thread.currentThread().getContextClassLoader();
        NativeLibClassLoader classloader = null;
        try {
            classloader = new NativeLibClassLoader(classPath.getUrls(), parent);
            classloader.addNativeClassPath(System.getProperty("java.library.path"));
            for (File folder : classPath.getNativeFolders()) {
                classloader.addNativeClassPath(folder);
            }
        } catch (IOException e) {
            throw new StartupException("Couldn't create NativeLibClassLoader", e);
        }
        Thread.currentThread().setContextClassLoader(classloader);
        return classloader;
    }

    private static void createLogDirectoryIfMissing(Config config) {
        File logDir = new File(config.logDir);
        if (!logDir.exists()) {
            if (logDir.mkdir()) {
                System.out.println("Created OFBiz log dir [" + logDir.getAbsolutePath() + "]");
            }
        }
    }

    private static void createRuntimeShutdownHook(
            Config config,
            List<StartupLoader> loaders,
            AtomicReference<ServerState> serverState) {

        if (config.useShutdownHook) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    shutdownServer(loaders, serverState, this);
                }
            });
        } else {
            System.out.println("Shutdown hook disabled");
        }
    }

    private static void loadStartupLoaders(Config config, 
            List<StartupLoader> loaders,
            List<StartupCommand> ofbizCommands,
            AtomicReference<ServerState> serverState,
            NativeLibClassLoader classloader) throws StartupException {

        synchronized (loaders) {
            for (Map<String, String> loaderMap : config.loaders) {
                if (serverState.get() == ServerState.STOPPING) {
                    return;
                }
                try {
                    String loaderClassName = loaderMap.get("class");
                    Class<?> loaderClass = classloader.loadClass(loaderClassName);
                    StartupLoader loader = (StartupLoader) loaderClass.newInstance();
                    loaders.add(loader); // add before loading, so unload can occur if error during loading
                    loader.load(config, ofbizCommands);
                } catch (ReflectiveOperationException e) {
                    throw new StartupException(e.getMessage(), e);
                }
            }
        }
        StringBuilder sb = new StringBuilder();
        for (String path : classloader.getNativeLibPaths()) {
            if (sb.length() > 0) {
                sb.append(File.pathSeparator);
            }
            sb.append(path);
        }
        System.setProperty("java.library.path", sb.toString());
        serverState.compareAndSet(ServerState.STARTING, ServerState.RUNNING);
    }

    private static void executeShutdownAfterLoadIfConfigured(
            Config config,
            List<StartupLoader> loaders,
            AtomicReference<ServerState> serverState,
            Thread adminServer) {

        if (config.shutdownAfterLoad) {
            stop(loaders, serverState, adminServer);
        }
    }
}
