/*******************************************************************************
 * 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 org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;

public class Config {

    public final InetAddress adminAddress;
    public final String adminKey;
    public final int adminPort;
    public final String awtHeadless;
    public final String containerConfig;
    public final String instrumenterClassName;
    public final String instrumenterFile;
    public final List<Map<String, String>> loaders;
    public final String logDir;
    public final String ofbizHome;
    public final boolean shutdownAfterLoad;
    public final String splashLogo;
    public final boolean useShutdownHook;
    public final Integer portOffset;

    Config(String[] args) throws IOException {
        String firstArg = args.length > 0 ? args[0] : "";
        // Needed when portoffset is used with these commands, start.properties fits for all of them
        if ("start-batch".equalsIgnoreCase(firstArg)
                || "start-debug".equalsIgnoreCase(firstArg)
                || "stop".equalsIgnoreCase(firstArg)
                || "-shutdown".equalsIgnoreCase(firstArg) // shutdown & status hack (was pre-existing to portoffset introduction, also useful with it)
                || "-status".equalsIgnoreCase(firstArg)) {
            firstArg = "start";
        }
        // default command is "start"
        if (firstArg == null || firstArg.trim().length() == 0) {
            firstArg = "start";
        }
        String config =  "org/ofbiz/base/start/" + firstArg + ".properties";

        Properties props = this.getPropertiesFile(config);
        System.out.println("Start.java using configuration file " + config);

        // set the ofbiz.home
        String ofbizHomeTmp = props.getProperty("ofbiz.home", ".");
        // get a full path
        if (ofbizHomeTmp.equals(".")) {
            ofbizHomeTmp = System.getProperty("user.dir");
            ofbizHomeTmp = ofbizHomeTmp.replace('\\', '/');
        }
        ofbizHome = ofbizHomeTmp;
        System.setProperty("ofbiz.home", ofbizHome);
        System.out.println("Set OFBIZ_HOME to - " + ofbizHome);

        // log directory
        logDir = getOfbizHomeProp(props, "ofbiz.log.dir", "runtime/logs");

        // container configuration
        containerConfig = getOfbizHomeProp(props, "ofbiz.container.config", "framework/base/config/ofbiz-containers.xml");

        // get the admin server info
        String serverHost = getProp(props, "ofbiz.admin.host", "127.0.0.1");

        String adminPortStr = getProp(props, "ofbiz.admin.port", "0");
        // set the admin key
        adminKey = getProp(props, "ofbiz.admin.key", "NA");

        // create the host InetAddress
        adminAddress = InetAddress.getByName(serverHost);

        // parse the port number
        int adminPortTmp;
        try {
            adminPortTmp = Integer.parseInt(adminPortStr);
            if (args.length > 0) {
                for (String arg : args) {
                    if (arg.toLowerCase().contains("portoffset=") && !arg.toLowerCase().contains("${portoffset}")) {
                        adminPortTmp = adminPortTmp != 0 ? adminPortTmp : 10523; // This is necessary because the ASF machines don't allow ports 1 to 3, see  INFRA-6790
                        adminPortTmp += Integer.parseInt(arg.split("=")[1]);
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("Error while parsing admin port number (so default to 10523) = " + e);
            adminPortTmp = 10523;
        }
        adminPort = adminPortTmp;

        // set the Derby system home
        String derbyPath = getProp(props, "derby.system.home", "runtime/data/derby");
        System.setProperty("derby.system.home", derbyPath);

        // check for shutdown hook
        if (System.getProperty("ofbiz.enable.hook") != null && System.getProperty("ofbiz.enable.hook").length() > 0) {
            useShutdownHook = "true".equalsIgnoreCase(System.getProperty("ofbiz.enable.hook"));
        } else if (props.getProperty("ofbiz.enable.hook") != null && props.getProperty("ofbiz.enable.hook").length() > 0) {
            useShutdownHook = "true".equalsIgnoreCase(props.getProperty("ofbiz.enable.hook"));
        } else {
            useShutdownHook = true;
        }

        // check for auto-shutdown
        if (System.getProperty("ofbiz.auto.shutdown") != null && System.getProperty("ofbiz.auto.shutdown").length() > 0) {
            shutdownAfterLoad = "true".equalsIgnoreCase(System.getProperty("ofbiz.auto.shutdown"));
        } else if (props.getProperty("ofbiz.auto.shutdown") != null && props.getProperty("ofbiz.auto.shutdown").length() > 0) {
            shutdownAfterLoad = "true".equalsIgnoreCase(props.getProperty("ofbiz.auto.shutdown"));
        } else {
            shutdownAfterLoad = false;
        }

        // set AWT headless mode
        awtHeadless = getProp(props, "java.awt.headless", null);
        if (awtHeadless != null) {
            System.setProperty("java.awt.headless", awtHeadless);
        }

        // get the splash logo
        splashLogo = props.getProperty("ofbiz.start.splash.logo", null);

        // set the default locale
        String localeString = props.getProperty("ofbiz.locale.default");
        if (localeString != null && localeString.length() > 0) {
            String locales[] = localeString.split("_");
            switch (locales.length) {
                case 1:
                    Locale.setDefault(new Locale(locales[0]));
                    break;
                case 2:
                    Locale.setDefault(new Locale(locales[0], locales[1]));
                    break;
                case 3:
                    Locale.setDefault(new Locale(locales[0], locales[1], locales[2]));
            }
            System.setProperty("user.language", localeString);
        }

        // set the default time zone
        String tzString = props.getProperty("ofbiz.timeZone.default");
        if (tzString != null && tzString.length() > 0) {
            TimeZone.setDefault(TimeZone.getTimeZone(tzString));
        }

        instrumenterClassName = getProp(props, "ofbiz.instrumenterClassName", null);
        instrumenterFile = getProp(props, "ofbiz.instrumenterFile", null);

        // loader classes
        List loadersTmp = new ArrayList<Map<String, String>>();
        int currentPosition = 1;
        Map<String, String> loader = null;
        while (true) {
            loader = new HashMap<String, String>();
            String loaderClass = props.getProperty("ofbiz.start.loader" + currentPosition);
            if (loaderClass == null || loaderClass.length() == 0) {
                break;
            } else {
                loader.put("class", loaderClass);
                loader.put("profiles", props.getProperty("ofbiz.start.loader" + currentPosition + ".loaders"));
                loadersTmp.add(Collections.unmodifiableMap(loader));
                currentPosition++;
            }
        }
        loaders = Collections.unmodifiableList(loadersTmp);

        // set the port offset
        Integer portOffset = 0;
        if (args != null) {
            for (String argument : args) {
                // arguments can prefix w/ a '-'. Just strip them off
                if (argument.startsWith("-")) {
                    int subIdx = 1;
                    if (argument.startsWith("--")) {
                        subIdx = 2;
                    }
                    argument = argument.substring(subIdx);
                }
                // parse the arguments
                if (argument.indexOf("=") != -1) {
                    String argumentName = argument.substring(0, argument.indexOf("="));
                    String argumentVal = argument.substring(argument.indexOf("=") + 1);
                    if ("portoffset".equalsIgnoreCase(argumentName) && !"${portoffset}".equals(argumentVal)) {
                        try {
                            portOffset = Integer.valueOf(argumentVal);
                        } catch (NumberFormatException e) {
                            System.out.println("Error while parsing portoffset (the default value 0 will be used) = " + e);
                        }
                    }
                }
            }
        }
        this.portOffset = portOffset;

    }

    private String getOfbizHomeProp(Properties props, String key, String def) {
        String value = System.getProperty(key);
        if (value != null)
            return value;
        return ofbizHome + "/" + props.getProperty(key, def);
    }

    private String getProp(Properties props, String key, String def) {
        String value = System.getProperty(key);
        if (value != null)
            return value;
        return props.getProperty(key, def);
    }

    private Properties getPropertiesFile(String config) throws IOException {
        InputStream propsStream = null;
        Properties props = new Properties();
        try {
            // first try classpath
            propsStream = getClass().getClassLoader().getResourceAsStream(config);
            if (propsStream != null) {
                props.load(propsStream);
            } else {
                throw new IOException();
            }
        } catch (IOException e) {
            // next try file location
            File propsFile = new File(config);
            if (propsFile != null) {
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(propsFile);
                    if (fis != null) {
                        props.load(fis);
                    }
                } catch (FileNotFoundException e2) {
                    // do nothing; we will see empty props below
                } finally {
                    if (fis != null) {
                        fis.close();
                    }
                }
            }
        } finally {
            if (propsStream != null) {
                propsStream.close();
            }
        }

        // check for empty properties
        if (props.isEmpty()) {
            throw new IOException("Cannot load configuration properties : " + config);
        }
        return props;
    }

    void initClasspath(Classpath classPath, Classpath libraryPath) throws Exception {
        // add OFBIZ_HOME to class path
        classPath.addClasspath(this.ofbizHome);
        File home = new File(this.ofbizHome);
        collectClasspathEntries(new File(home, "framework"), classPath, libraryPath);
        collectClasspathEntries(new File(home, "applications"), classPath, libraryPath);
        collectClasspathEntries(new File(home, "specialpurpose"), classPath, libraryPath);
        collectClasspathEntries(new File(home, "hot-deploy"), classPath, libraryPath);
        System.setProperty("java.library.path", libraryPath.toString());
        classPath.instrument(this.instrumenterFile, this.instrumenterClassName);
    }

    private void collectClasspathEntries(File folder, Classpath classpath, Classpath libraryPath) throws ParserConfigurationException, IOException, SAXException {
        if (!folder.exists() && !folder.isDirectory()) {
            return;
        }
        FileFilter componentLoadFilter = new FileFilter() {
            public boolean accept(File pathname) {
                return "component-load.xml".equals(pathname.getName());
            }
        };
        FileFilter folderFilter = new FileFilter() {
            public boolean accept(File pathname) {
                return pathname.isDirectory();
            }
        };
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        File[] componentLoadFiles;
        List<File> ofbizComponents = new ArrayList<File>();
        componentLoadFiles = folder.listFiles(componentLoadFilter);
        if (componentLoadFiles != null && componentLoadFiles.length == 1) {
            File componentLoadFile = componentLoadFiles[0];
            // parse and get folder names to be processed
            Document document = builder.parse(componentLoadFile);
            Element element = document.getDocumentElement();
            NodeList loadComponents = element.getElementsByTagName("load-component");
            for (int i = 0; i < loadComponents.getLength(); i++) {
                Node loadComponent = loadComponents.item(i);
                NamedNodeMap attributes = loadComponent.getAttributes();
                Node componentLocation = attributes.getNamedItem("component-location");
                if (componentLocation == null) {
                    continue;
                }
                ofbizComponents.add(new File(new File(folder, componentLocation.getNodeValue()), "ofbiz-component.xml"));
            }
        } else {
            File[] componentFolders = folder.listFiles(folderFilter);
            for (File componentFolder: componentFolders) {
                File ofbizComponent = new File(componentFolder, "ofbiz-component.xml");
                if (ofbizComponent.exists()) {
                    ofbizComponents.add(ofbizComponent);
                }
            }
        }
        String nativeLibExt = System.mapLibraryName("someLib").replace("someLib", "").toLowerCase();
        for (File ofbizComponent: ofbizComponents) {
            Document document = builder.parse(ofbizComponent);
            Element element = document.getDocumentElement();
            if (element.hasAttribute("enabled")) {
                if ("false".equals(element.getAttribute("enabled"))) {
                    continue;
                }
            }
            NodeList classpathEntries = element.getElementsByTagName("classpath");
            for (int i = 0; i < classpathEntries.getLength(); i++) {
                Node classpathEntry = classpathEntries.item(i);
                NamedNodeMap attributes = classpathEntry.getAttributes();
                Node type = attributes.getNamedItem("type");
                if (type == null || !("jar".equals(type.getNodeValue()) || "dir".equals(type.getNodeValue()))) {
                    continue;
                }
                Node location = attributes.getNamedItem("location");
                String locationValue = location.getNodeValue();
                locationValue = locationValue.replace('\\', '/');
                // set the location to not have a leading slash
                if (locationValue.startsWith("/")) {
                    locationValue = locationValue.substring(1);
                }
                String dirLoc = locationValue;
                if (dirLoc.endsWith("/*")) {
                    // strip off the slash splat
                    dirLoc = locationValue.substring(0, locationValue.length() - 2);
                }

                String fileNameSeparator = ("\\".equals(File.separator) ? "\\" + File.separator : File.separator);
                dirLoc = dirLoc.replaceAll("/+|\\\\+", fileNameSeparator);
                File path = new File(ofbizComponent.getParent(), dirLoc);
                if (path.exists()) {
                    if (path.isDirectory()) {
                        if ("dir".equals(type.getNodeValue())) {
                            classpath.addComponent(path.toString());
                        }
                        // load all .jar, .zip files and native libs in this directory
                        boolean containsNativeLibs = false;
                        for (File file: path.listFiles()) {
                            String fileName = file.getName().toLowerCase();
                            if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
                                classpath.addComponent(file);
                            } else if (fileName.endsWith(nativeLibExt)) {
                                containsNativeLibs = true;
                            }
                        }
                        if (containsNativeLibs) {
                            libraryPath.addComponent(path);
                        }
                    } else {
                        classpath.addComponent(path.toString());
                    }
                }
            }
        }
    }

}
