/*
 * 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.openejb.arquillian.common;

import org.apache.openejb.loader.ProvisioningUtil;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.loader.provisining.ProvisioningResolver;
import org.apache.tomee.util.QuickServerXmlParser;
import org.codehaus.swizzle.stream.ReplaceStringsInputStream;
import org.jboss.arquillian.container.spi.client.container.LifecycleException;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.api.spec.JavaArchive;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import static java.util.Collections.emptyMap;

/**
 * @version $Rev$ $Date$
 */
public class Setup {
    private static final Logger LOGGER = Logger.getLogger(Setup.class.getName()); // JUL is used by arquillian so that's fine
    public static final String TOMEE_BEAN_DISCOVERER_JAR = "lib" + File.separator + "xx-arquillian-tomee-bean-discoverer.jar"; // starts with xx to not be filtered
    private static final String DEFAULT_MEM_CONFIG = (javaVersion() >= 1.8 ? "" : "-XX:PermSize=64m -XX:MaxPermSize=256m ")
                                                            + "-Xmx512m -Xms256m -XX:ReservedCodeCacheSize=64m";

    private static double javaVersion() {
        try {
            return Double.parseDouble(System.getProperty("java.version", "1.7").substring(0, 3));
        } catch (final Exception nfe) {
            return 1.6;
        }
    }

    public static void exportProperties(final File tomeeHome, final TomEEConfiguration c, final boolean defaultMem) {
        final int httpPort = c.getHttpPort();
        System.setProperty("java.naming.provider.url", "http://" + c.getHost() + ":" + httpPort + "/tomee/ejb");
        System.setProperty("connect.tries", "90");
        System.setProperty("server.http.port", String.valueOf(httpPort));
        System.setProperty("server.shutdown.port", String.valueOf(c.getStopPort()));
        if (defaultMem) {
            System.setProperty("java.opts", DEFAULT_MEM_CONFIG + " -Dtomee.httpPort=" + httpPort);
        } else {
            System.setProperty("java.opts", "-Dtomee.httpPort=" + httpPort);
        }
        System.setProperty("openejb.home", tomeeHome.getAbsolutePath());
        System.setProperty("tomee.home", tomeeHome.getAbsolutePath());
    }

    public static void updateServerXml(final File tomeeHome, final TomEEConfiguration configuration) throws IOException {
        final File serverXml = Files.path(new File(tomeeHome.getAbsolutePath()), "conf", "server.xml");
        if (!serverXml.exists()) {
            return;
        }

        final QuickServerXmlParser ports = QuickServerXmlParser.parse(serverXml);
        if (configuration.getKeepServerXmlAsThis()) {
            // force ports to be able to stop the server and get @ArquillianResource
            configuration.setHttpPort(Integer.parseInt(ports.http()));
            configuration.setStopPort(Integer.parseInt(ports.stop()));
            return; // in this case we don't want to override the conf
        }

        final Map<String, String> replacements = new HashMap<>();
        replacements.put(ports.http(), String.valueOf(configuration.getHttpPort()));
        replacements.put(ports.https(), String.valueOf(configuration.getHttpsPort()));
        replacements.put(ports.stop(), String.valueOf(configuration.getStopPort()));
        replacements.put(ports.ajp(), String.valueOf(ajpPort(configuration)));

        if (configuration.isUnpackWars()) {
            replacements.put("unpackWARs=\"false\"", "unpackWARs=\"true\"");
        } else {
            replacements.put("unpackWARs=\"true\"", "unpackWARs=\"false\"");
        }

        replace(replacements, serverXml, true);
    }

    public static File findHome(File directory) {

        directory = directory.getAbsoluteFile();

        final File f = findHomeImpl(directory);

        if (null == f) {
            LOGGER.log(Level.INFO, "Unable to find home in: " + directory);
        }

        return f;
    }

    public static File findHomeImpl(final File directory) {
        final File conf = new File(directory, "conf").getAbsoluteFile();
        final File webapps = new File(directory, "webapps").getAbsoluteFile();

        if (conf.exists() && conf.isDirectory() && webapps.exists() && webapps.isDirectory()) {
            return directory;
        }

        final File[] files = directory.listFiles();
        if (null != files) {

            for (final File file : files) {
                if (".".equals(file.getName()) || "..".equals(file.getName())) {
                    continue;
                }

                final File found = findHome(file);

                if (found != null) {
                    return found;
                }
            }
        }

        return null;
    }

    public static File downloadAndUnpack(final File dir, final String artifactID, final String defaultTempDir) throws LifecycleException {

        final File zipFile = downloadFile(artifactID, null, defaultTempDir);

        Zips.unzip(zipFile, dir);

        return findHome(dir);
    }

    public static File downloadFile(final String artifactName, final String altUrl, final String defaultTempDir) {
        final String cache = SystemInstance.isInitialized() ?
            SystemInstance.get().getOptions().get(ProvisioningResolver.OPENEJB_DEPLOYER_CACHE_FOLDER, (String) null) :
            System.getProperty(ProvisioningResolver.OPENEJB_DEPLOYER_CACHE_FOLDER);
        if (cache == null && defaultTempDir != null) { // let the user override it
            System.setProperty(ProvisioningResolver.OPENEJB_DEPLOYER_CACHE_FOLDER, defaultTempDir);
        }

        try {
            final File artifact = MavenCache.getArtifact(artifactName, altUrl);
            if (artifact == null) {
                throw new NullPointerException(String.format("No such artifact: %s", artifactName));
            }
            return artifact.getAbsoluteFile();
        } finally {
            if (cache == null) {
                System.clearProperty(ProvisioningResolver.OPENEJB_DEPLOYER_CACHE_FOLDER);
            }
        }
    }

    public static boolean isRunning(final String host, final int port) {
        Socket socket = null;
        try {
            socket = new Socket(host, port);
            socket.getOutputStream().close();
            return true;
        } catch (final Exception e) {
            return false;
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (final IOException ignored) {
                    // no-op
                }
            }
        }
    }

    public static void replace(final Map<String, String> replacements, final File file, final boolean escape) throws IOException {

        InputStream in = IO.read(file);

        if (escape) {
            final Map<String, String> escaped = new HashMap<>();
            for (final Map.Entry<String, String> entry : replacements.entrySet()) {
                final String key = entry.getKey();
                final String value = entry.getValue();
                if (key.startsWith("\"") && key.endsWith("\"")) {
                    escaped.put(key, value);
                } else {
                    escaped.put("\"" + key + "\"", "\"" + value + "\"");
                }
            }

            replacements.clear();
            replacements.putAll(escaped);
        }

        in = new ReplaceStringsInputStream(in, replacements);

        final String data = IO.slurp(in);

        IO.copy(data.getBytes(), file);

        if (LOGGER.isLoggable(Level.FINE)) {
            IO.copy(data.getBytes(), System.out);
        }
    }

    public static void removeUselessWebapps(final File tomeeHome, final String... exceptions) {
        final File webapps = new File(tomeeHome, "webapps");
        if (webapps.isDirectory()) {
            final File[] files = webapps.listFiles();
            if (files != null) {
                for (final File webapp : files) {
                    boolean delete = true;
                    if (exceptions != null) {
                        for (final String ignore : exceptions) {
                            if (webapp.getName().equals(ignore)) {
                                delete = false;
                                break;
                            }
                        }
                    }
                    if (delete) {
                        org.apache.openejb.loader.Files.delete(webapp);
                    }
                }
            }
        }
    }

    public static void configureServerXml(final File tomeeHome, final TomEEConfiguration configuration) throws IOException {

        if (configuration.getServerXml() != null) {

            final File serverXml = new File(configuration.getServerXml());

            if (!serverXml.exists()) {
                LOGGER.severe("Provided server.xml doesn't exist: '" + serverXml.getPath() + "'");
            } else {

                // Read in the contents to memory so we can avoid re-reading for parsing
                final String data = IO.slurp(serverXml);

                IO.copy(data.getBytes(), Files.path(tomeeHome, "conf", "server.xml"));
            }
        }
        updateServerXml(tomeeHome, configuration);
    }

    private static int ajpPort(final TomEEConfiguration config) {
        try {
            final Method ajbPort = config.getClass().getMethod("getAjpPort");
            return (Integer) ajbPort.invoke(config);
        } catch (final Exception e) {
            return Integer.parseInt(QuickServerXmlParser.DEFAULT_AJP_PORT);
        }
    }

    public static void configureSystemProperties(final File tomeeHome, final TomEEConfiguration configuration) {
        final File file = Files.path(tomeeHome, "conf", "system.properties");

        // Must use an actual properties object to avoid duplicate keys
        final Properties properties = new Properties();

        if (file.exists()) {
            try {
                IO.readProperties(file, properties);
            } catch (final IOException e) {
                LOGGER.log(Level.SEVERE, "Can't read " + file.getAbsolutePath(), e);
            }
        }

        if (configuration.getProperties() != null) {
            try {
                final InputStream bytes = IO.read(configuration.getProperties().getBytes());
                IO.readProperties(bytes, properties);
            } catch (final IOException e) {
                LOGGER.log(Level.SEVERE, "Can't parse <property name=\"properties\"> value '" + configuration.getProperties() + "'", e);
            }
        }

        if (configuration.isQuickSession()) {
            properties.put("openejb.session.manager", "org.apache.tomee.catalina.session.QuickSessionManager");
        }

        if (configuration.isUnsafeEjbd() && "*".equals(properties.getProperty("tomee.serialization.class.blacklist", "-").trim())) {
            properties.remove("tomee.serialization.class.blacklist");
            properties.put("tomee.serialization.class.whitelist", "*");
            System.setProperty("tomee.serialization.class.blacklist", System.getProperty("tomee.serialization.class.blacklist", "-"));
            reloadClientSerializationConfig();
        }

        try {
            IO.writeProperties(file, properties);
        } catch (final IOException e) {
            LOGGER.log(Level.SEVERE, "Can't save system properties " + file.getAbsolutePath(), e);
        }
    }

    public static void reloadClientSerializationConfig() {
        try {
            Thread.currentThread().getContextClassLoader().loadClass("org.apache.openejb.client.EjbObjectInputStream")
                .getMethod("reloadResolverConfig").invoke(null);
        } catch (final IllegalAccessException | InvocationTargetException | ClassNotFoundException | NoSuchMethodException e) {
            // not a pb normally
        }
    }


    public static void synchronizeFolder(final File tomeeHome, final String src, final String dir) {
        if (src != null && !src.isEmpty()) {
            final File confSrc = new File(src);
            if (confSrc.exists()) {
                final File conf = new File(tomeeHome, dir);
                final Collection<File> files = org.apache.openejb.loader.Files.collect(confSrc, TrueFilter.INSTANCE);
                files.remove(confSrc);
                for (final File f : files) {
                    if (f.equals(confSrc) || f.getName().startsWith(".")) {
                        continue;
                    }

                    final String relativize = relativize(f, confSrc);
                    if (f.isDirectory()) {
                        final String path = dir + '/' + relativize;
                        Files.mkdir(new File(tomeeHome, path));
                        synchronizeFolder(tomeeHome, f.getAbsolutePath(), path);
                    } else {
                        try {
                            final File to = new File(conf, relativize);
                            Files.mkdir(to.getParentFile());
                            org.apache.openejb.loader.IO.copy(f, to);
                        } catch (final Exception e) {
                            LOGGER.log(Level.WARNING, "Ignoring copy of " + f.getAbsolutePath(), e);
                        }
                    }
                }
            } else {
                LOGGER.warning("Can't find " + confSrc.getAbsolutePath());
            }
        }
    }

    private static String relativize(final File f, final File base) {
        return f.getAbsolutePath().substring(base.getAbsolutePath().length() + 1);
    }

    public static void installArquillianBeanDiscoverer(final File home) {
        final File destination = new File(home, TOMEE_BEAN_DISCOVERER_JAR);
        ShrinkWrap.create(JavaArchive.class, destination.getName())
                .addManifest() // avoid NPE from org.apache.tomcat.util.scan.StandardJarScanner.processManifest()
                .addClasses(BeanDicovererInstaller.class, TestClassDiscoverer.class, ArquillianFilterRunner.class, Discover.class)
                .addAsManifestResource(new StringAsset(BeanDicovererInstaller.class.getName()), ArchivePaths.create("org.apache.openejb.extension"))
                .as(ZipExporter.class).exportTo(destination, true);
    }

    public static void removeArquillianBeanDiscoverer(final File home) {
        final File destination = new File(home, TOMEE_BEAN_DISCOVERER_JAR);
        Files.delete(destination);
    }

    public static Map<File, String> addTomEELibraries(final File libFolder, final String additionalLibs, final boolean parseArgs) {
        if (additionalLibs == null) {
            return emptyMap();
        }
        final String libs = additionalLibs.trim();
        if (libs.isEmpty()) {
            return emptyMap();
        }

        try { // initializing the SystemInstance because we'll need it for configuration
            if (!SystemInstance.isInitialized()) {
                SystemInstance.init(new Properties());
            }
        } catch (final Exception e) {
            // no-op
        }

        final Map<File, String> configs = new HashMap<>();
        for (final String lib : libs.split("\n")) {
            final String trim = lib.trim();
            if (trim.isEmpty() || trim.startsWith("#")) {
                continue;
            }

            final String args;
            if (parseArgs) { // javaagent friendly
                int argsIdx = trim.indexOf('=');
                if (argsIdx < 0) {
                    argsIdx = trim.indexOf('?');
                }
                if (argsIdx > 0) {
                    args = trim.substring(argsIdx);
                } else {
                    args = "";
                }
            } else {
                args = null;
            }

            if (trim.startsWith("remove:")) { // like mvn plugin, needed to use plus but switch something like the jpa provider
                final String prefix = trim.substring("remove:".length());
                final File[] children = libFolder.listFiles(new FilenameFilter() {
                    @Override
                    public boolean accept(final File dir, final String name) {
                        return name.startsWith(prefix);
                    }
                });
                if (children != null && children.length > 0) {
                    for (final File child : children) {
                        if (!IO.delete(child) && child.getName().endsWith(".jar")) { // try to rename it to have it ignored
                            child.renameTo(new File(child.getParentFile(), child.getName() + "_renamed"));
                        }
                    }
                }
            } else {
                final Set<String> locations = ProvisioningUtil.realLocation(trim);
                for (final String location : locations) {
                    final File from = new File(location);
                    try {
                        final File to = new File(libFolder, from.getName());
                        org.apache.openejb.loader.IO.copy(from, to);
                        if (args != null) {
                            configs.put(to, args);
                        }
                    } catch (final IOException e) {
                        throw new IllegalArgumentException(e);
                    }
                }
            }
        }
        return configs;
    }

    private static class TrueFilter implements FileFilter {
        private static final TrueFilter INSTANCE = new TrueFilter();

        @Override
        public boolean accept(final File pathname) {
            return true;
        }
    }
}
