// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================

package org.eclipse.jetty.deploy.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.junit.Assert;

/**
 * Allows for setting up a Jetty server for testing based on XML configuration files.
 */
public class XmlConfiguredJetty
{
    private List<URL> xmlConfigurations;
    private Properties properties = new Properties();
    private Server server;
    private int serverPort;
    private String scheme = HttpSchemes.HTTP;
    private File jettyHome;

    public XmlConfiguredJetty() throws IOException
    {
        String testname = new Throwable().getStackTrace()[1].getClassName();

        xmlConfigurations = new ArrayList<URL>();
        properties = new Properties();

        jettyHome = MavenTestingUtils.getTargetTestingDir(testname);
        deleteContents(jettyHome); // Ensure that we are working with a pristene directory
        // Prepare Jetty.Home (Test) dir
        jettyHome.mkdirs();

        File logsDir = new File(jettyHome,"logs");
        logsDir.mkdirs();

        File etcDir = new File(jettyHome,"etc");
        etcDir.mkdirs();
        IO.copyFile(MavenTestingUtils.getTestResourceFile("etc/realm.properties"),new File(etcDir,"realm.properties"));
        IO.copyFile(MavenTestingUtils.getTestResourceFile("etc/webdefault.xml"),new File(etcDir,"webdefault.xml"));

        File contextsDir = new File(jettyHome,"contexts");
        if (contextsDir.exists())
        {
            deleteContents(contextsDir);
        }
        contextsDir.mkdirs();
        File webappsDir = new File(jettyHome,"webapps");
        if (webappsDir.exists())
        {
            deleteContents(webappsDir);
        }
        webappsDir.mkdirs();
        File tmpDir = new File(jettyHome,"tmp");
        tmpDir.mkdirs();

        // Setup properties
        System.setProperty("java.io.tmpdir",tmpDir.getAbsolutePath());
        properties.setProperty("jetty.home",jettyHome.getAbsolutePath());
        System.setProperty("jetty.home",jettyHome.getAbsolutePath());
        properties.setProperty("test.basedir",MavenTestingUtils.getBasedir().getAbsolutePath());
        properties.setProperty("test.resourcesdir",MavenTestingUtils.getTestResourcesDir().getAbsolutePath());
        properties.setProperty("test.webapps",webappsDir.getAbsolutePath());
        properties.setProperty("test.targetdir",MavenTestingUtils.getTargetDir().getAbsolutePath());

        // Write out configuration for use by ConfigurationManager.
        File testConfig = MavenTestingUtils.getTargetFile("xml-configured-jetty.properties");
        FileOutputStream out = new FileOutputStream(testConfig);
        properties.store(out,"Generated by " + XmlConfiguredJetty.class.getName());
    }

    public void addConfiguration(File xmlConfigFile) throws MalformedURLException
    {
        xmlConfigurations.add(xmlConfigFile.toURI().toURL());
    }

    public void addConfiguration(String testConfigName) throws MalformedURLException
    {
        addConfiguration(MavenTestingUtils.getTestResourceFile(testConfigName));
    }

    public void addConfiguration(URL xmlConfig)
    {
        xmlConfigurations.add(xmlConfig);
    }

    public void assertNoWebAppContexts()
    {
        List<WebAppContext> contexts = getWebAppContexts();
        if (contexts.size() > 0)
        {
            for (WebAppContext context : contexts)
            {
                System.out.println("WebAppContext should not exist:\n" + toString(context));
            }
            Assert.assertEquals("Contexts.size",0,contexts.size());
        }
    }

    public String getResponse(String path) throws IOException
    {
        URI destUri = getServerURI().resolve(path);
        URL url = destUri.toURL();

        URLConnection conn = url.openConnection();

        InputStream in = null;
        try
        {
            in = conn.getInputStream();
            return IO.toString(in);
        }
        finally
        {
            IO.close(in);
        }
    }

    public void assertResponseContains(String path, String needle) throws IOException
    {
        System.out.println("Issuing request to " + path);
        String content = getResponse(path);
        Assert.assertTrue("Content should contain <" + needle + ">, instead got <" + content + ">",content.contains(needle));
    }

    public void assertWebAppContextsExists(String... expectedContextPaths)
    {
        List<WebAppContext> contexts = getWebAppContexts();
        if (expectedContextPaths.length != contexts.size())
        {
            System.out.println("## Expected Contexts");
            for (String expected : expectedContextPaths)
            {
                System.out.println(expected);
            }
            System.out.println("## Actual Contexts");
            for (WebAppContext context : contexts)
            {
                System.out.printf("%s ## %s%n",context.getContextPath(),context);
            }
            Assert.assertEquals("Contexts.size",expectedContextPaths.length,contexts.size());
        }

        for (String expectedPath : expectedContextPaths)
        {
            boolean found = false;
            for (WebAppContext context : contexts)
            {
                if (context.getContextPath().equals(expectedPath))
                {
                    found = true;
                    break;
                }
            }
            Assert.assertTrue("Did not find Expected Context Path " + expectedPath,found);
        }
    }

    public void copyContext(String srcName, String destName) throws IOException
    {
        System.out.printf("Copying Context: %s -> %s%n",srcName,destName);
        File srcDir = MavenTestingUtils.getTestResourceDir("contexts");
        File destDir = new File(jettyHome,"contexts");

        File srcFile = new File(srcDir,srcName);
        File destFile = new File(destDir,destName);

        copyFile("Context",srcFile,destFile);
    }

    private void copyFile(String type, File srcFile, File destFile) throws IOException
    {
        PathAssert.assertFileExists(type + " File",srcFile);
        IO.copyFile(srcFile,destFile);
        PathAssert.assertFileExists(type + " File",destFile);
        System.out.printf("Copy %s: %s%n  To %s: %s%n",type,srcFile,type,destFile);
        System.out.printf("Destination Exists: %s - %s%n",destFile.exists(),destFile);
    }

    public void copyWebapp(String srcName, String destName) throws IOException
    {
        System.out.printf("Copying Webapp: %s -> %s%n",srcName,destName);
        File srcDir = MavenTestingUtils.getTestResourceDir("webapps");
        File destDir = new File(jettyHome,"webapps");

        File srcFile = new File(srcDir,srcName);
        File destFile = new File(destDir,destName);

        copyFile("Webapp",srcFile,destFile);
    }

    private void deleteContents(File dir)
    {
        System.out.printf("Delete  (dir) %s/%n",dir);
        for (File file : dir.listFiles())
        {
            // Safety measure. only recursively delete within target directory.
            if (file.isDirectory() && file.getAbsolutePath().contains("target" + File.separator))
            {
                deleteContents(file);
                Assert.assertTrue("Delete failed: " + file.getAbsolutePath(),file.delete());
            }
            else
            {
                System.out.printf("Delete (file) %s%n",file);
                Assert.assertTrue("Delete failed: " + file.getAbsolutePath(),file.delete());
            }
        }
    }

    public DeploymentManager getActiveDeploymentManager()
    {
        List<DeploymentManager> depmans = server.getBeans(DeploymentManager.class);
        Assert.assertEquals("DeploymentManager bean count",1,depmans.size());
        return depmans.get(0);
    }

    public File getJettyDir(String name)
    {
        return new File(jettyHome,name);
    }

    public File getJettyHome()
    {
        return jettyHome;
    }

    public String getScheme()
    {
        return scheme;
    }

    public Server getServer()
    {
        return server;
    }

    public int getServerPort()
    {
        return serverPort;
    }

    public URI getServerURI() throws UnknownHostException
    {
        StringBuffer uri = new StringBuffer();
        uri.append(this.scheme).append("://");
        uri.append(InetAddress.getLocalHost().getHostAddress());
        uri.append(":").append(this.serverPort);
        return URI.create(uri.toString());
    }

    public List<WebAppContext> getWebAppContexts()
    {
        List<WebAppContext> contexts = new ArrayList<WebAppContext>();
        HandlerCollection handlers = (HandlerCollection)server.getHandler();
        System.out.println(server.dump());
        Handler children[] = handlers.getChildHandlers();

        for (Handler handler : children)
        {
            if (handler instanceof WebAppContext)
            {
                WebAppContext context = (WebAppContext)handler;
                contexts.add(context);
            }
        }

        return contexts;
    }

    @SuppressWarnings("unchecked")
    public void load() throws Exception
    {
        XmlConfiguration last = null;
        Object[] obj = new Object[this.xmlConfigurations.size()];

        // Configure everything
        for (int i = 0; i < this.xmlConfigurations.size(); i++)
        {
            URL configURL = this.xmlConfigurations.get(i);
            XmlConfiguration configuration = new XmlConfiguration(configURL);
            if (last != null)
            {
                configuration.getIdMap().putAll(last.getIdMap());
            }
            configuration.setProperties(properties);
            obj[i] = configuration.configure();
            last = configuration;
        }

        // Test for Server Instance.
        Server foundServer = null;
        int serverCount = 0;
        for (int i = 0; i < this.xmlConfigurations.size(); i++)
        {
            if (obj[i] instanceof Server)
            {
                if (obj[i].equals(foundServer))
                {
                    // Identical server instance found
                    break;
                }
                foundServer = (Server)obj[i];
                serverCount++;
            }
        }

        if (serverCount <= 0)
        {
            throw new Exception("Load failed to configure a " + Server.class.getName());
        }

        Assert.assertEquals("Server load count",1,serverCount);

        this.server = foundServer;
        this.server.setGracefulShutdown(10);

    }

    public void printHandlers(PrintStream out)
    {
        Handler handler = server.getHandler();
        out.println(toString(handler));
    }

    public void removeContext(String name)
    {
        File destDir = new File(jettyHome,"contexts");
        File contextFile = new File(destDir,name);
        if (contextFile.exists())
        {
            Assert.assertTrue("Delete of Context file: " + contextFile.getAbsolutePath(),contextFile.delete());
        }
    }

    public void setProperty(String key, String value)
    {
        properties.setProperty(key,value);
    }

    public void setScheme(String scheme)
    {
        this.scheme = scheme;
    }

    public void start() throws Exception
    {
        Assert.assertNotNull("Server should not be null (failed load?)",server);

        server.start();

        // Find the active server port.
        this.serverPort = (-1);
        Connector connectors[] = server.getConnectors();
        for (int i = 0; i < connectors.length; i++)
        {
            Connector connector = connectors[i];
            if (connector.getLocalPort() > 0)
            {
                this.serverPort = connector.getLocalPort();
                break;
            }
        }

        Assert.assertTrue("Server Port is between 1 and 65535. Actually <" + serverPort + ">",(1 <= this.serverPort) && (this.serverPort <= 65535));

        // Uncomment to have server start and continue to run (without exiting)
        // System.out.printf("Listening to port %d%n",this.serverPort);
        // server.join();
    }

    public void stop() throws Exception
    {
        server.stop();
    }

    public String toString(Handler handler)
    {
        if (handler instanceof HandlerCollection)
        {
            return ((HandlerCollection)handler).dump();
        }

        if (handler instanceof AbstractHandler)
        {
            return ((AbstractHandler)handler).dump();
        }

        return handler.toString();
    }

    public void waitForDirectoryScan()
    {
        int ms = 2000;
        System.out.printf("Waiting %d milliseconds for AppProvider to process directory scan ...%n",ms);
        try
        {
            Thread.sleep(ms);
        }
        catch (InterruptedException ignore)
        {
            /* ignore */
        }
    }
}
