/*
 * 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.tuscany.maven.plugin;

import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;

import org.apache.catalina.LifecycleException;
import org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.startup.Tomcat;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.tuscany.sca.shell.Shell;

/**
 * Maven Mojo to run the Tuscany Shell and install the project as an SCA contribution.
 * 
 * Invoked with "mvn tuscany:run"
 * 
 * @goal run
 * @requiresDependencyResolution runtime
 * @execute phase="test-compile"
 * @description Runs Tuscany directly from a SCA conribution maven project
 */
public class TuscanyRunMojo extends AbstractMojo {

    /**
     * The maven project.
     *
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

    /**
     * The project artifactId.
     * 
     * @parameter expression="${project.artifactId}"
     * @required
     */
    protected String artifactId;

    /**
     * The project packaging.
     * 
     * @parameter expression=".${project.packaging}"
     * @required
     */
    protected String packaging;

    /**
     * The project build output directory
     * 
     * @parameter expression="${project.build.outputDirectory}"
     * @required
     */
    protected File buildDirectory;

    /**
     * The project build output directory
     * 
     * @parameter expression="${project.build.finalName}"
     * @required
     */
    protected File finalName;

    /**
     * @parameter expression="${domainURI}" default-value="uri:default"
     */
    private String domainURI;

    /**
     * @parameter expression="${nodeXML}"
     */
    private String nodeXML;

    /**
     * @parameter expression="${contributions}" 
     */
    private String[] contributions;

    /**
     * @parameter expression="${mainClass}"
     */
    private String mainClass;

    /**
     * @parameter expression="${arguments}"
     */
    private String[] arguments;

    public void execute() throws MojoExecutionException, MojoFailureException {
        if (mainClass != null) {
            executeMainMethod();
        } else if (".war".equals(packaging)) {
            try {
                executeTomcat();
            } catch (Exception e) {
                throw new MojoExecutionException("Exception running Tuscany/Tomcat", e);
            }
        } else {
            executeShell();
        }
    }

    private void executeTomcat() throws ServletException, LifecycleException, MalformedURLException {
        getLog().info("Starting Tuscany/Tomcat...");
        
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);

        tomcat.setBaseDir("target");
        String appBase = "../src/main/webapp";
        tomcat.getHost().setAppBase(".");
        String contextPath = "/" + artifactId;

        StandardServer server = (StandardServer)tomcat.getServer();
        server.setParentClassLoader(getMainClassLoader());
        AprLifecycleListener listener = new AprLifecycleListener();
        server.addLifecycleListener(listener);

        tomcat.addWebapp(contextPath, appBase);
        tomcat.start();
        tomcat.getServer().await();
    }

    private void executeShell() throws MojoExecutionException {
        getLog().info("Starting Tuscany Shell...");

        if (nodeXML != null && nodeXML.length() > 0) {
            try {
                Shell.main(new String[]{"-nodeXML:" + nodeXML});
            } catch (Exception e) {
                throw new MojoExecutionException("Exception in Shell", e);
            }
        } else {
            List<String> contributionList = new ArrayList<String>();

            addProjectContribution(contributionList);

            addAdditionalContributions(contributionList);

            contributionList.add(0, "-help");
            contributionList.add(0, domainURI);
            
            try {
                Shell.main(contributionList.toArray(new String[contributionList.size()]));
            } catch (Exception e) {
                throw new MojoExecutionException("Exception in Shell", e);
            }
        }
        
        getLog().info("Tuscany Shell stopped.");
    }

    private void addAdditionalContributions(List<String> contributionList) throws MojoExecutionException {
        if (contributions != null) {
            for (String s : contributions) {
                if (new File(s).exists()) {
                    contributionList.add(s);
                } else {
                    boolean found = false;
                    for (Object o : project.getDependencyArtifacts()) {
                        Artifact a = (Artifact) o;
                        if (a.getId().startsWith(s)) {
                            try {
                                contributionList.add(a.getFile().toURI().toURL().toString());
                            } catch (MalformedURLException e) {
                                throw new MojoExecutionException("", e);
                            }
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        throw new IllegalArgumentException("Contribution not found as file or dependency: " + s);
                    }
                }
            }
        }
    }

    protected void addProjectContribution(List<String> cs) throws MojoExecutionException {
        try {

            File contributionFile = new File(buildDirectory.getParent(), finalName.getName());
            if (!contributionFile.exists()) {
                contributionFile = new File(buildDirectory.getParent(), "classes");
            }
            if (!contributionFile.exists()) {
                contributionFile = new File(buildDirectory.getParent(), finalName.getName() + packaging);
            }
            
            String contribution = contributionFile.toURI().toURL().toString();
            getLog().info("Project contribution: " + contribution);
            cs.add(contribution);
            
        } catch (MalformedURLException e) {
            throw new MojoExecutionException("", e);
        }
    }

    public void executeMainMethod() throws MojoExecutionException, MojoFailureException {
        getLog().info("Invoking " + mainClass + " class main method...");
        
        if (arguments == null) {
            arguments = new String[0];
        }

        try {
            Method main = getMainClassLoader().loadClass(mainClass).getMethod("main", new Class[] {String[].class});
            main.invoke(main, new Object[] {arguments});
        } catch (NoSuchMethodException e) {
            throw new MojoExecutionException("The specified mainClass doesn't contain a main method with appropriate signature", e);
        } catch (Exception e) {
            throw new MojoExecutionException("exception invoking main method", e);
        }
    }

    private ClassLoader getMainClassLoader() throws MalformedURLException {
        ClassLoader parent = Thread.currentThread().getContextClassLoader();
        List<URL> classPathEntries = new ArrayList<URL>();
        classPathEntries.add(new File(project.getBuild().getOutputDirectory()).toURI().toURL());
        for (Object o : project.getRuntimeArtifacts()) {
            Artifact a = (Artifact) o;
            classPathEntries.add( a.getFile().toURI().toURL() );
        }
        return new URLClassLoader((URL[])classPathEntries.toArray(new URL[]{}), parent );
    }

}
