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

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Start - OFBiz Container(s) Startup Class
 *
 */
public class Start {

    private enum Control {
        SHUTDOWN {
            void processRequest(Start start, PrintWriter writer) {
                if (start.serverState.get() == ServerState.STOPPING) {
                    writer.println("IN-PROGRESS");
                } else {
                    writer.println("OK");
                    writer.flush();
                    start.stopServer();
                }
            }
        }, STATUS {
            void processRequest(Start start, PrintWriter writer) {
                writer.println(start.serverState.get());
            }
        }, FAIL {
            void processRequest(Start start, PrintWriter writer) {
                writer.println("FAIL");
            }
        };

        abstract void processRequest(Start start, PrintWriter writer);
    }

    private static void help(PrintStream out) {
        out.println("");
        out.println("Usage: java -jar ofbiz.jar [command] [arguments]");
        out.println("-both    -----> Run simultaneously the POS (Point of Sales) application and OFBiz standard");
        out.println("-help, -? ----> This screen");
        out.println("-install -----> Run install (create tables/load data)");
        out.println("-pos     -----> Run the POS (Point of Sales) application");
        out.println("-setup -------> Run external application server setup");
        out.println("-start -------> Start the server");
        out.println("-status ------> Status of the server");
        out.println("-shutdown ----> Shutdown the server");
        out.println("-test --------> Run the JUnit test script");
        out.println("[no config] --> Use default config");
        out.println("[no command] -> Start the server w/ default config");
    }

    private enum Command {
        HELP, HELP_ERROR, STATUS, SHUTDOWN, COMMAND
    }

    private static Command checkCommand(Command command, Command wanted) {
        if (wanted == Command.HELP || wanted.equals(command)) {
            return wanted;
        } else if (command == null) {
            return wanted;
        } else {
            System.err.println("Duplicate command detected(was " + command + ", wanted " + wanted);
            return Command.HELP_ERROR;
        }
    }

    public static void main(String[] args) throws StartupException {
        Command command = null;
        List<String> loaderArgs = new ArrayList<String>(args.length);
        for (String arg: args) {
            if (arg.equals("-help") || arg.equals("-?")) {
                command = checkCommand(command, Command.HELP);
            } else if (arg.equals("-status")) {
                command = checkCommand(command, Command.STATUS);
            } else if (arg.equals("-shutdown")) {
                command = checkCommand(command, Command.SHUTDOWN);
            } else if (arg.startsWith("-")) {
                command = checkCommand(command, Command.COMMAND);
                loaderArgs.add(arg.substring(1));
            } else {
                command = checkCommand(command, Command.COMMAND);
                if (command == Command.COMMAND) {
                    loaderArgs.add(arg);
                } else {
                    command = Command.HELP_ERROR;
                }
            }
        }
        if (command == null) {
            command = Command.COMMAND;
            loaderArgs.add("start");
        }
        if (command == Command.HELP) {
            help(System.out);
            return;
        } else if (command == Command.HELP_ERROR) {
            help(System.err);
            System.exit(1);
        }
        Start start = new Start();
        start.init(args, command == Command.COMMAND);
        try {
            if (command == Command.STATUS) {
                System.out.println("Current Status : " + start.status());
            } else if (command == Command.SHUTDOWN) {
                System.out.println("Shutting down server : " + start.shutdown());
            } else {
                // general start
                start.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(99);
        }
    }

    private enum ServerState {
        STARTING, RUNNING, STOPPING;

        public String toString() {
            return name().charAt(0) + name().substring(1).toLowerCase();
        }
    }

    private Config config = null;
    private List<String> loaderArgs = new ArrayList<String>();
    private final ArrayList<StartupLoader> loaders = new ArrayList<StartupLoader>();
    private AtomicReference<ServerState> serverState = new AtomicReference<ServerState>(ServerState.STARTING);
    private Thread adminPortThread = null;

    private void createListenerThread() throws StartupException {
        if (config.adminPort > 0) {
            this.adminPortThread = new AdminPortThread();
            this.adminPortThread.start();
        } else {
            System.out.println("Admin socket not configured; set to port 0");
        }
    }

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

    public void init(String[] args) throws StartupException {
        init(args, true);
    }

    public void init(String[] args, boolean fullInit) throws StartupException {
        String globalSystemPropsFileName = System.getProperty("ofbiz.system.props");
        if (globalSystemPropsFileName != null) {
            FileInputStream stream = null;
            try {
                stream = new FileInputStream(globalSystemPropsFileName);
                System.getProperties().load(stream);
            } catch (IOException e) {
                throw (StartupException) new StartupException("Couldn't load global system props").initCause(e);
            } finally {
                if (stream != null){
                    try {
                        stream.close();
                    } catch (IOException e) {
                        throw (StartupException) new StartupException("Couldn't close stream").initCause(e);
                    }
                }
            }
        }
        try {
            this.config = Config.getInstance(args);
        } catch (IOException e) {
            throw (StartupException) new StartupException("Couldn't not fetch config instance").initCause(e);
        }
        // parse the startup arguments
        if (args.length > 1) {
            this.loaderArgs.addAll(Arrays.asList(args).subList(1, args.length));
        }

        if (!fullInit) {
            return;
        }
        // initialize the classpath
        initClasspath();

        // create the log directory
        createLogDirectory();

        // create the listener thread
        createListenerThread();

        // set the shutdown hook
        if (config.useShutdownHook) {
            Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { shutdownServer(); } });
        } else {
            System.out.println("Shutdown hook disabled");
        }

        // initialize the startup loaders
        initStartLoaders();
    }

    private void initClasspath() throws StartupException {
        Classpath classPath = new Classpath(System.getProperty("java.class.path"));
        try {
            this.config.initClasspath(classPath);
        } catch (IOException e) {
            throw (StartupException) new StartupException("Couldn't initialized classpath").initCause(e);
        }
        // Set the classpath/classloader
        System.setProperty("java.class.path", classPath.toString());
        ClassLoader classloader = classPath.getClassLoader();
        Thread.currentThread().setContextClassLoader(classloader);
        if (System.getProperty("DEBUG") != null) {
            System.out.println("Startup Classloader: " + classloader.toString());
            System.out.println("Startup Classpath: " + classPath.toString());
        }
    }

    private void initStartLoaders() throws StartupException {
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        synchronized (this.loaders) {
            // initialize the loaders
            for (String loaderClassName: config.loaders) {
                if (this.serverState.get() == ServerState.STOPPING) {
                    return;
                }
                try {
                    Class<?> loaderClass = classloader.loadClass(loaderClassName);
                    StartupLoader loader = (StartupLoader) loaderClass.newInstance();
                    loader.load(config, loaderArgs.toArray(new String[loaderArgs.size()]));
                    loaders.add(loader);
                } catch (ClassNotFoundException e) {
                    throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                } catch (InstantiationException e) {
                    throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                } catch (IllegalAccessException e) {
                    throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                }
            }
            this.loaders.trimToSize();
        }
        return;
    }

    private String sendSocketCommand(Control control) throws IOException, ConnectException {
        String response = "OFBiz is Down";

        try {
        Socket socket = new Socket(config.adminAddress, config.adminPort);

        // send the command
        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
        writer.println(config.adminKey + ":" + control);
        writer.flush();

        // read the reply
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        response = reader.readLine();

        reader.close();

        // close the socket
        writer.close();
        socket.close();

        } catch (ConnectException e) {
            System.out.println("Could not connect to " + config.adminAddress + ":" + config.adminPort);
        }
        return response;
    }

    public String shutdown() throws IOException {
        return sendSocketCommand(Control.SHUTDOWN);
    }

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

    // org.apache.commons.daemon.Daemon.start()
    public void start() throws Exception {
        if (!startStartLoaders()) {
            if (this.serverState.get() == ServerState.STOPPING) {
                return;
            } else {
                throw new Exception("Error during start.");
            }
        }
        if (config.shutdownAfterLoad) {
            stopServer();
        }
    }

    /**
     * Returns <code>true</code> if all loaders were started.
     * 
     * @return <code>true</code> if all loaders were started.
     */
    private boolean startStartLoaders() {
        synchronized (this.loaders) {
            // start the loaders
            for (StartupLoader loader: this.loaders) {
                if (this.serverState.get() == ServerState.STOPPING) {
                    return false;
                }
                try {
                    loader.start();
                } catch (StartupException e) {
                    e.printStackTrace();
                    return false;
                }
            }
        }
        return this.serverState.compareAndSet(ServerState.STARTING, ServerState.RUNNING);
    }

    public String status() throws IOException {
        try {
            return sendSocketCommand(Control.STATUS);
        } catch (ConnectException e) {
            return "Not Running";
        } catch (IOException e) {
            throw e;
        }
    }

    public void stopServer() {
        shutdownServer();
        System.exit(0);
    }

    // org.apache.commons.daemon.Daemon.destroy()
    public void destroy() {
        // FIXME: undo init() calls.
    }

    // org.apache.commons.daemon.Daemon.stop()
    public void stop() {
        shutdownServer();
    }

    private class AdminPortThread extends Thread {
        private ServerSocket serverSocket = null;

        AdminPortThread() throws StartupException {
            super("AdminPortThread");
            try {
                this.serverSocket = new ServerSocket(config.adminPort, 1, config.adminAddress);
            } catch (IOException e) {
                throw (StartupException) new StartupException("Couldn't create server socket(" + config.adminAddress + ":" + config.adminPort + ")").initCause(e);
            }
            setDaemon(false);
        }

        private void processClientRequest(Socket client) throws IOException {
            BufferedReader reader = null;
            PrintWriter writer = null;
            try {
                reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
                String request = reader.readLine();
                writer = new PrintWriter(client.getOutputStream(), true);
                Control control;
                if (request != null && !request.isEmpty() && request.contains(":")) {
                    String key = request.substring(0, request.indexOf(':'));
                    if (key.equals(config.adminKey)) {
                        control = Control.valueOf(request.substring(request.indexOf(':') + 1));
                        if (control == null) {
                            control = Control.FAIL;
                        }
                    } else {
                        control = Control.FAIL;
                    }
                } else {
                    control = Control.FAIL;
                }
                control.processRequest(Start.this, writer);
            } finally {
                if (reader != null) {
                    reader.close();
                }
                if (writer != null) {
                    writer.flush();
                    writer.close();
                }
            }
        }

        @Override
        public void run() {
            System.out.println("Admin socket configured on - " + config.adminAddress + ":" + config.adminPort);
            while (!Thread.interrupted()) {
                try {
                    Socket clientSocket = serverSocket.accept();
                    System.out.println("Received connection from - " + clientSocket.getInetAddress() + " : " + clientSocket.getPort());
                    processClientRequest(clientSocket);
                    clientSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
