//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  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.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.maven.plugin;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ShutdownMonitor;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.xml.XmlConfiguration;



/**
 * Starter Class which is exec'ed to create a new jetty process. Used by the JettyRunForked mojo.
 */
public class Starter
{ 
    private static final Logger LOG = Log.getLogger(Starter.class);

    private List<File> jettyXmls; // list of jetty.xml config files to apply - Mandatory
    private File contextXml; //name of context xml file to configure the webapp - Mandatory

    private Server server;
    private JettyWebAppContext webApp;

    
    private int stopPort=0;
    private String stopKey=null;
    private Properties props;
    private String token;

    
    /**
     * Artifact
     *
     * A mock maven Artifact class as the maven jars are not put onto the classpath for the
     * execution of this class.
     *
     */
    public class Artifact
    {
        public String gid;
        public String aid;
        public String path;
        public Resource resource;
        
        public Artifact (String csv)
        {
            if (csv != null && !"".equals(csv))
            {
                String[] atoms = StringUtil.csvSplit(csv);
                if (atoms.length >= 3)
                {
                    gid = atoms[0].trim();
                    aid = atoms[1].trim();
                    path = atoms[2].trim();
                }
            }
        }
        
        public Artifact (String gid, String aid, String path)
        {
            this.gid = gid;
            this.aid = aid;
            this.path = path;
        }
        
        public boolean equals(Object o)
        {
            if (!(o instanceof Artifact))
                return false;
            
            Artifact ao = (Artifact)o;
            return (((gid == null && ao.gid == null) || (gid != null && gid.equals(ao.gid)))
                    &&  ((aid == null && ao.aid == null) || (aid != null && aid.equals(ao.aid))));      
        }
    }
    
    
    
    public void configureJetty () throws Exception
    {
        LOG.debug("Starting Jetty Server ...");
        Resource.setDefaultUseCaches(false);
        
        //apply any configs from jetty.xml files first 
        applyJettyXml ();

        //ensure there's a connector
        ServerSupport.configureConnectors(server, null);

        //check if contexts already configured, create if not
        ServerSupport.configureHandlers(server, null);
        
        //Set up list of default Configurations to apply to a webapp
        ServerSupport.configureDefaultConfigurationClasses(server);
        
        webApp = new JettyWebAppContext();
        
        //configure webapp from properties file describing unassembled webapp
        configureWebApp();
        
        //make it a quickstart if the quickstart-web.xml file exists
        if (webApp.getTempDirectory() != null)
        {
            File qs = new File (webApp.getTempDirectory(), "quickstart-web.xml");
            if (qs.exists() && qs.isFile())
                webApp.setQuickStartWebDescriptor(Resource.newResource(qs));
        }
        
        //set up the webapp from the context xml file provided
        //NOTE: just like jetty:run mojo this means that the context file can
        //potentially override settings made in the pom. Ideally, we'd like
        //the pom to override the context xml file, but as the other mojos all
        //configure a WebAppContext in the pom (the <webApp> element), it is 
        //already configured by the time the context xml file is applied.
        if (contextXml != null)
        {
            XmlConfiguration xmlConfiguration = new XmlConfiguration(Resource.toURL(contextXml));
            xmlConfiguration.getIdMap().put("Server",server);
            xmlConfiguration.configure(webApp);
        }

        ServerSupport.addWebApplication(server, webApp);

        if(stopPort>0 && stopKey!=null)
        {
            ShutdownMonitor monitor = ShutdownMonitor.getInstance();
            monitor.setPort(stopPort);
            monitor.setKey(stopKey);
            monitor.setExitVm(true);
        }
    }
    
    public void configureWebApp ()
    throws Exception
    {
        if (props == null)
            return;
        
        //apply a properties file that defines the things that we configure in the jetty:run plugin:
        // - the context path
        String str = (String)props.get("context.path");
        if (str != null)
            webApp.setContextPath(str);
        
        
        // - web.xml
        str = (String)props.get("web.xml");
        if (str != null)
            webApp.setDescriptor(str); 
        
        str = (String)props.get("quickstart.web.xml");
        if (str != null)
            webApp.setQuickStartWebDescriptor(Resource.newResource(new File(str)));
        
        // - the tmp directory
        str = (String)props.getProperty("tmp.dir");
        if (str != null)
            webApp.setTempDirectory(new File(str.trim()));

        str = (String)props.getProperty("tmp.dir.persist");
        if (str != null)
            webApp.setPersistTempDirectory(Boolean.valueOf(str));
        
        //Get the calculated base dirs which includes the overlays
        str = (String)props.getProperty("base.dirs");
        if (str != null && !"".equals(str.trim()))
        {
            ResourceCollection bases = new ResourceCollection(StringUtil.csvSplit(str));
            webApp.setWar(null);
            webApp.setBaseResource(bases);
        }

        //Get the original base dirs without the overlays
        str = (String)props.get("base.dirs.orig");
        if (str != null && !"".equals(str.trim()))
        {
            ResourceCollection bases = new ResourceCollection(StringUtil.csvSplit(str));
            webApp.setAttribute ("org.eclipse.jetty.resources.originalBases", bases);
        }
        
        //For overlays
        str = (String)props.getProperty("maven.war.includes");
        List<String> defaultWarIncludes = fromCSV(str);
        str = (String)props.getProperty("maven.war.excludes");
        List<String> defaultWarExcludes = fromCSV(str);
       
        //List of war artifacts
        List<Artifact> wars = new ArrayList<Artifact>();
        
        //List of OverlayConfigs
        TreeMap<String, OverlayConfig> orderedConfigs = new TreeMap<String, OverlayConfig>();
        Enumeration<String> pnames = (Enumeration<String>)props.propertyNames();
        while (pnames.hasMoreElements())
        {
            String n = pnames.nextElement();
            if (n.startsWith("maven.war.artifact"))
            {
                Artifact a = new Artifact((String)props.get(n));
                a.resource = Resource.newResource("jar:"+Resource.toURL(new File(a.path)).toString()+"!/");
                wars.add(a);
            }
            else if (n.startsWith("maven.war.overlay"))
            {
                OverlayConfig c = new OverlayConfig ((String)props.get(n), defaultWarIncludes, defaultWarExcludes);
                orderedConfigs.put(n,c);
            }
        }
        
    
        Set<Artifact> matchedWars = new HashSet<Artifact>();
        
        //process any overlays and the war type artifacts
        List<Overlay> overlays = new ArrayList<Overlay>();
        for (OverlayConfig config:orderedConfigs.values())
        {
            //overlays can be individually skipped
            if (config.isSkip())
                continue;

            //an empty overlay refers to the current project - important for ordering
            if (config.isCurrentProject())
            {
                Overlay overlay = new Overlay(config, null);
                overlays.add(overlay);
                continue;
            }

            //if a war matches an overlay config
            Artifact a = getArtifactForOverlayConfig(config, wars);
            if (a != null)
            {
                matchedWars.add(a);
                SelectiveJarResource r = new SelectiveJarResource(new URL("jar:"+Resource.toURL(new File(a.path)).toString()+"!/"));
                r.setIncludes(config.getIncludes());
                r.setExcludes(config.getExcludes());
                Overlay overlay = new Overlay(config, r);
                overlays.add(overlay);
            }
        }

        //iterate over the left over war artifacts and unpack them (without include/exclude processing) as necessary
        for (Artifact a: wars)
        {
            if (!matchedWars.contains(a))
            {
                Overlay overlay = new Overlay(null, a.resource);
                overlays.add(overlay);
            }
        }

        webApp.setOverlays(overlays);
     

        // - the equivalent of web-inf classes
        str = (String)props.getProperty("classes.dir");
        if (str != null && !"".equals(str.trim()))
        {
            webApp.setClasses(new File(str));
        }
        
        str = (String)props.getProperty("testClasses.dir"); 
        if (str != null && !"".equals(str.trim()))
        {
            webApp.setTestClasses(new File(str));
        }


        // - the equivalent of web-inf lib
        str = (String)props.getProperty("lib.jars");
        if (str != null && !"".equals(str.trim()))
        {
            List<File> jars = new ArrayList<File>();
            String[] names = StringUtil.csvSplit(str);
            for (int j=0; names != null && j < names.length; j++)
                jars.add(new File(names[j].trim()));
            webApp.setWebInfLib(jars);
        }
        
    }

    public void getConfiguration (String[] args)
    throws Exception
    {
        for (int i=0; i<args.length; i++)
        {
            //--stop-port
            if ("--stop-port".equals(args[i]))
                stopPort = Integer.parseInt(args[++i]);

            //--stop-key
            if ("--stop-key".equals(args[i]))
                stopKey = args[++i];

            //--jettyXml
            if ("--jetty-xml".equals(args[i]))
            {
                jettyXmls = new ArrayList<File>();
                String[] names = StringUtil.csvSplit(args[++i]);
                for (int j=0; names!= null && j < names.length; j++)
                {
                    jettyXmls.add(new File(names[j].trim()));
                }  
            }

            //--context-xml
            if ("--context-xml".equals(args[i]))
            {
                contextXml = new File(args[++i]);
            }

            //--props
            if ("--props".equals(args[i]))
            {
                File f = new File(args[++i].trim());
                props = new Properties();
                try (InputStream in = new FileInputStream(f))
                {
                    props.load(in);
                }
            }
            
            //--token
            if ("--token".equals(args[i]))
            {
                token = args[++i].trim();
            }
        }
    }


    public void run() throws Exception
    {
        LOG.info("Started Jetty Server");
        server.start();  
    }

    
    public void join () throws Exception
    {
        server.join();
    }
    
    
    public void communicateStartupResult (Exception e)
    {
        if (token != null)
        {
            if (e==null)
                System.out.println(token);
            else
                System.out.println(token+"\t"+e.getMessage());
        }
    }
    
    
    /**
     * Apply any jetty xml files given
     * @throws Exception if unable to apply the xml
     */
    public void applyJettyXml() throws Exception
    {
        Server tmp = ServerSupport.applyXmlConfigurations(server, jettyXmls);
        if (server == null)
            server = tmp;
        
        if (server == null)
            server = new Server();
    }




    protected void prependHandler (Handler handler, HandlerCollection handlers)
    {
        if (handler == null || handlers == null)
            return;

        Handler[] existing = handlers.getChildHandlers();
        Handler[] children = new Handler[existing.length + 1];
        children[0] = handler;
        System.arraycopy(existing, 0, children, 1, existing.length);
        handlers.setHandlers(children);
    }
    
    
    
    protected Artifact getArtifactForOverlayConfig (OverlayConfig c, List<Artifact> wars)
    {
        if (wars == null || wars.isEmpty() || c == null)
            return null;

        Artifact war = null;
        Iterator<Artifact> itor = wars.iterator();
        while(itor.hasNext() && war == null)
        {
            Artifact a = itor.next();
            if (c.matchesArtifact(a.gid, a.aid, null))
                war = a;
        }
        return war;
    }


    /**
     * @param csv
     * @return
     */
    private List<String> fromCSV (String csv)
    {
        if (csv == null || "".equals(csv.trim()))
            return null;
        String[] atoms = StringUtil.csvSplit(csv);
        List<String> list = new ArrayList<String>();
        for (String a:atoms)
        {
            list.add(a.trim());
        }
        return list;
    }
    
    public static final void main(String[] args)
    {
        if (args == null)
           System.exit(1);
       
       Starter starter = null;
       try
       {
           starter = new Starter();
           starter.getConfiguration(args);
           starter.configureJetty();
           starter.run();
           starter.communicateStartupResult(null);
           starter.join();
       }
       catch (Exception e)
       {
           starter.communicateStartupResult(e);
           e.printStackTrace();
           System.exit(1);
       }

    }
}
