/*
 * 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.servicemix.maven.plugin.jbi;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.Profile;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.servicemix.common.packaging.Consumes;
import org.apache.servicemix.common.packaging.Provides;
import org.codehaus.plexus.util.FileUtils;

/**
 * A Mojo used to build the jbi.xml file for a service unit.
 * 
 * @author <a href="pdodds@apache.org">Philip Dodds</a>
 * @version $Id: GenerateComponentDescriptorMojo 314956 2005-10-12 16:27:15Z
 *          brett $
 * @goal generate-jbi-service-assembly-descriptor
 * @phase generate-resources
 * @requiresDependencyResolution runtime
 * @description generates the jbi.xml deployment descriptor for a service unit
 */
public class GenerateServiceAssemblyDescriptorMojo extends AbstractJbiMojo {

    public static final String JBI_NAMESPACE = "http://java.sun.com/xml/ns/jbi";

    public static final String UTF_8 = "UTF-8";

    public class Connection {
        private Consumes consumes;

        private Provides provides;

        public Consumes getConsumes() {
            return consumes;
        }

        public void setConsumes(Consumes consumes) {
            this.consumes = consumes;
        }

        public Provides getProvides() {
            return provides;
        }

        public void setProvides(Provides provides) {
            this.provides = provides;
        }
    }

    /**
     * Whether the jbi.xml should be generated or not.
     * 
     * @parameter
     */
    private Boolean generateJbiDescriptor = Boolean.TRUE;

    /**
     * The component name.
     * 
     * @parameter expression="${project.artifactId}"
     */
    private String name;

    /**
     * The component description.
     * 
     * @parameter expression="${project.name}"
     */
    private String description;

    /**
     * Character encoding for the auto-generated application.xml file.
     * 
     * @parameter
     */
    private String encoding = UTF_8;

    /**
     * Directory where the application.xml file will be auto-generated.
     * 
     * @parameter expression="${project.build.directory}/classes/META-INF"
     */
    private String generatedDescriptorLocation;

    /**
     * The location of a file containing the connections elements that can be
     * merged into the jbi.xml
     * 
     * @parameter expression="${basedir}/src/main/resources/jbi-connections.xml"
     */
    private File jbiConnectionsFile;

    /**
     * Dependency graph
     */
    private JbiResolutionListener listener;

    public void execute() throws MojoExecutionException, MojoFailureException {

        getLog()
                .debug(
                        " ======= GenerateServiceAssemlbyDescriptorMojo settings =======");
        getLog().debug("workDirectory[" + workDirectory + "]");
        getLog().debug("generateJbiDescriptor[" + generateJbiDescriptor + "]");
        getLog().debug("name[" + name + "]");
        getLog().debug("description[" + description + "]");
        getLog().debug("encoding[" + encoding + "]");
        getLog().debug(
                "generatedDescriptorLocation[" + generatedDescriptorLocation
                        + "]");

        if (!generateJbiDescriptor.booleanValue()) {
            getLog().debug("Generation of jbi.xml is disabled");
            return;
        }

        // Generate jbi descriptor and copy it to the build directory
        getLog().info("Generating jbi.xml");
        try {
            listener = resolveProject();
            generateJbiDescriptor();
        } catch (JbiPluginException e) {
            throw new MojoExecutionException("Failed to generate jbi.xml", e);
        }

        try {
            FileUtils.copyFileToDirectory(new File(generatedDescriptorLocation,
                    JBI_DESCRIPTOR), new File(getWorkDirectory(), META_INF));
        } catch (IOException e) {
            throw new MojoExecutionException(
                    "Unable to copy jbi.xml to final destination", e);
        }
    }

    /**
     * Generates the deployment descriptor if necessary.
     * 
     * @throws MojoExecutionException
     */
    protected void generateJbiDescriptor() throws JbiPluginException,
            MojoExecutionException {
        File outputDir = new File(generatedDescriptorLocation);
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }

        File descriptor = new File(outputDir, JBI_DESCRIPTOR);

        List serviceUnits = new ArrayList();

        Set artifacts = project.getArtifacts();
        for (Iterator iter = artifacts.iterator(); iter.hasNext();) {
        	
            Artifact artifact = (Artifact) iter.next();
            // TODO: utilise appropriate methods from project builder
            ScopeArtifactFilter filter = new ScopeArtifactFilter(
                    Artifact.SCOPE_RUNTIME);
            if (!artifact.isOptional() && filter.include(artifact)
                    && (artifact.getDependencyTrail().size() == 2)) {
                MavenProject project = null;
                try {
                    project = projectBuilder.buildFromRepository(artifact,
                            remoteRepos, localRepo);
                } catch (ProjectBuildingException e) {
                    getLog().warn(
                            "Unable to determine packaging for dependency : "
                                    + artifact.getArtifactId()
                                    + " assuming jar");
                }
                if ((project != null)
                        && (project.getPackaging().equals("jbi-service-unit"))) {
                    DependencyInformation info = new DependencyInformation();
                    info.setName(artifact.getArtifactId());
                    String fileName = artifact.getFile().getName();
                    if (fileName == null) {
                        // the name is not defined in the POM
                        // try to use the artifactId
                        // as the artifactId is mandatory by maven, we don't
                        // need any additional test
                        fileName = artifact.getArtifactId();
                    }
                    if (fileName.equals("classes")) {
                    	fileName = artifact.getArtifactId() + "-" + artifact.getVersion() + ".jar";
                    }
                    String suName = getServiceUnitName(project);
                    if (suName != null && suName.length() > 0) {
                    	fileName = suName;
                    } else {
                    	fileName = fileName.substring(0, fileName.lastIndexOf('.')) + ".zip";
                    }
                    info.setFilename(fileName);
                    info.setComponent(getComponentName(project, artifacts, artifact));
                    info.setDescription(project.getDescription());
                    serviceUnits.add(info);
                }

            }
        }

        List orderedServiceUnits = reorderServiceUnits(serviceUnits);

        List connections = getConnections();

        JbiServiceAssemblyDescriptorWriter writer = new JbiServiceAssemblyDescriptorWriter(
                encoding);
        writer.write(descriptor, name, description, orderedServiceUnits,
                connections);
    }

    /**
     * Used to return a list of connections if they have been found in the
     * jbiConnectionsFile
     * 
     * @return A list of connections
     * @throws MojoExecutionException
     */
    private List getConnections() throws MojoExecutionException {

        if (jbiConnectionsFile.exists()) {
            return parseConnectionsXml();
        } else {
            return new ArrayList();
        }
    }

    /**
     * Parse the jbiConnectionsFile
     * 
     * @return
     * @throws MojoExecutionException
     */
    private List parseConnectionsXml() throws MojoExecutionException {
        getLog().info(
                "Picking up connections from "
                        + jbiConnectionsFile.getAbsolutePath());
        List connections = new ArrayList();
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(jbiConnectionsFile);

            Node servicesNode = doc.getFirstChild();
            if (servicesNode instanceof Element
                  && XmlDescriptorHelper.isElement(servicesNode, JBI_NAMESPACE, "connections")) {
                // We will process the children
                Element servicesElement = (Element) servicesNode;
                NodeList children = servicesElement.getChildNodes();
                for (int i = 0; i < children.getLength(); i++) {
                    if (XmlDescriptorHelper.isElement(children.item(i), JBI_NAMESPACE, "connection")) {
                        Connection connection = new Connection();
                        NodeList connectionChildren = children.item(i).getChildNodes();
                        for (int x = 0; x < connectionChildren.getLength(); x++) {
                            if (connectionChildren.item(x) instanceof Element) {
                                Element childElement = (Element) connectionChildren.item(x);
                                if (XmlDescriptorHelper.isElement(
                                        childElement, JBI_NAMESPACE, "consumer")) {
                                    Consumes newConsumes = new Consumes();
                                    newConsumes.setEndpointName(XmlDescriptorHelper
                                                    .getEndpointName(childElement));
                                    newConsumes.setInterfaceName(XmlDescriptorHelper
                                                    .getInterfaceName(childElement));
                                    newConsumes.setServiceName(XmlDescriptorHelper
                                                    .getServiceName(childElement));
                                    connection.setConsumes(newConsumes);
                                } else if (XmlDescriptorHelper.isElement(
                                        childElement, JBI_NAMESPACE, "provider")) {
                                    Provides newProvides = new Provides();
                                    newProvides.setEndpointName(XmlDescriptorHelper
                                                    .getEndpointName(childElement));
                                    newProvides.setInterfaceName(XmlDescriptorHelper
                                                    .getInterfaceName(childElement));
                                    newProvides.setServiceName(XmlDescriptorHelper
                                                    .getServiceName(childElement));
                                    connection.setProvides(newProvides);
                                }
                            }
                        }
                        connections.add(connection);
                    }
                }
            }
            getLog().info("Found " + connections.size() + " connections");
            return connections;
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to parse "
                    + jbiConnectionsFile.getAbsolutePath());
        }
    }

    /**
     * Re-orders the service units to match order in the dependencies section of
     * the pom
     * 
     * @param serviceUnits
     * @throws MojoExecutionException
     */
    private List reorderServiceUnits(List serviceUnits) throws MojoExecutionException {

        // TODO Currently we get the model back by re-parsing it however in the
        // future we should be able to use the getModel() - there should be a
        // fix post 2.0.4

        // Iterator dependencies =
        // project.getModel().getDependencies().iterator();

        // For now we will need to reparse the pom without processing
        Iterator dependencies = getReparsedDependencies();

        List orderedServiceUnits = new ArrayList();
        parseDependencies(serviceUnits, dependencies, orderedServiceUnits);
        
        //get chance the go through the active profile dependencies so that the SU dependency 
        //from active profile can also be taken into account

        List activeProfileList = project.getActiveProfiles();
        for (Iterator iter = activeProfileList.iterator(); iter.hasNext();) {
                Profile activeProfile = (Profile) iter.next();
                parseDependencies(serviceUnits, activeProfile.getDependencies().iterator(), orderedServiceUnits);
                
        }

        return orderedServiceUnits;
    }

	private void parseDependencies(List serviceUnits, Iterator dependencies,
			List orderedServiceUnits) throws MojoExecutionException {
		while (dependencies.hasNext()) {
            Dependency dependency = (Dependency) dependencies.next();
            if (dependency.getArtifactId().contains("${")) {
                int first = dependency.getArtifactId().indexOf("${");
                int last  = dependency.getArtifactId().indexOf("}");
                String property = dependency.getArtifactId().substring(first + 2, last);
                Object propValue = project.getProperties().get(property);
                if (propValue == null) {
                    throw new MojoExecutionException("The value for the property " + property + "is not set."
                            + "Jbi descriptor may not be generated properly");
                }
                String propString = (String) propValue;
                String artifactID = dependency.getArtifactId().replace("${" + property + "}", propString);
                dependency.setArtifactId(artifactID);
            }
            for (Iterator it = serviceUnits.iterator(); it.hasNext();) {
                DependencyInformation serviceUnitInfo = (DependencyInformation) it
                        .next();
                if (dependency.getArtifactId()
                        .equals(serviceUnitInfo.getName())) {
                	//check if this su already added to descriptor
                	boolean addedSu = false;
                	for (Iterator innerIt = orderedServiceUnits.iterator();innerIt.hasNext();) {
                		DependencyInformation addedServiceUnitInfo = (DependencyInformation) innerIt.next();
                		if (addedServiceUnitInfo.getName().equals(serviceUnitInfo.getName())) {
                			addedSu = true;
                		}
                	}
                	if (!addedSu) {
                		getLog().debug("Adding " + serviceUnitInfo.getFilename());
                		orderedServiceUnits.add(serviceUnitInfo);
                	}
                }

            }
        }
	}

    private Iterator getReparsedDependencies() throws MojoExecutionException {
        MavenXpp3Reader mavenXpp3Reader = new MavenXpp3Reader();
        try {
            Model model = mavenXpp3Reader.read(new FileReader(new File(project
                    .getBasedir(), "pom.xml")), false);
            return model.getDependencies().iterator();
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to reparse the pom.xml");
        }
    }

    private String getComponentName(MavenProject project, Set artifacts,
            Artifact suArtifact) throws MojoExecutionException {

        getLog().info(
                "Determining component name for service unit "
                        + project.getArtifactId());
        if (project.getProperties().getProperty("componentName") != null) {
            return project.getProperties().getProperty("componentName");
        }

        JbiResolutionListener.Node n = listener.getNode(suArtifact);
        for (Iterator it = n.getChildren().iterator(); it.hasNext();) {
            JbiResolutionListener.Node child = (JbiResolutionListener.Node) it
                    .next();
            MavenProject artifactProject = null;
            try {
                getLog().info(child.getArtifact().toString());
                
                artifactProject = projectBuilder
                    .buildFromRepository(child.getArtifact(), 
                                         remoteRepos, localRepo);
            } catch (ProjectBuildingException e) {
                getLog().warn(
                        "Unable to determine packaging for dependency : "
                                + child.getArtifact().getArtifactId()
                                + " assuming jar");
                getLog().debug(e);                
            }      
            if (artifactProject != null) {
                getLog().info(
                              "Project " + artifactProject + " packaged "
                              + artifactProject.getPackaging());
            }
            if ((artifactProject != null)
                    && (artifactProject.getPackaging().equals("jbi-component"))) {
                return child.getArtifact().getArtifactId();
            }
        }
        
        //as the jbi-component packaged dependency may already have been pruned
        //in case of multiple sus which belong to same jbi-component exist in one sa, so we
        //just check the dependencies from this su maven project to find the jbi-component name
        
        for (Iterator it = project.getArtifacts().iterator(); it.hasNext();) {
            Artifact artifactInSUPom = (Artifact) it
                    .next();
            MavenProject artifactProject = null;
            try {
                artifactProject = projectBuilder.buildFromRepository(artifactInSUPom
                        , remoteRepos, localRepo);
            } catch (ProjectBuildingException e) {
                getLog().warn(
                        "Unable to determine packaging for dependency : "
                                + artifactInSUPom.getArtifactId()
                                + " assuming jar");
                getLog().debug(e);                
            }
            if (artifactProject != null) {
                getLog().info(
                    "Project " + artifactProject + " packaged "
                            + artifactProject.getPackaging());
            }
            if ((artifactProject != null)
                    && (artifactProject.getPackaging().equals("jbi-component"))) {
                return artifactInSUPom.getArtifactId();
            }
        }

        throw new MojoExecutionException(
                "The service unit "
                        + project.getArtifactId()
                        + " does not have a dependency which is packaged as a jbi-component or a project property 'componentName'");
    }

}
