package org.codehaus.mojo.webstart.generator;

/*
 * Copyright 2005 Nick C
 *
 * Licensed 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.
 */

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.log.NullLogSystem;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.project.MavenProject;
import org.codehaus.mojo.webstart.AbstractJnlpMojo;

import java.io.File;
import java.io.FileWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

/**
 * Generates a JNLP deployment descriptor
 *
 * @author ngc
 * @author <a href="jerome@coffeebreaks.org">Jerome Lacoste</a>
 */
public class Generator
{
    private VelocityEngine engine = new VelocityEngine();

    private AbstractJnlpMojo config;

    private Template template;

    private File outputFile;

    /**
     * @param task
     * @param resourceLoaderPath  used to find the template in conjunction to inputFileTemplatePath
     * @param outputFile
     * @param inputFileTemplatePath relative to resourceLoaderPath
     */
    public Generator( AbstractJnlpMojo task, File resourceLoaderPath, File outputFile, String inputFileTemplatePath )
    {
        this.config = task;

        this.outputFile = outputFile;
        //initialise the resource loader to use the class loader
        Properties props = new Properties();

        props.setProperty( VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS,
                           "org.apache.velocity.runtime.log.NullLogSystem" );
        props.setProperty( "file.resource.loader.path", resourceLoaderPath.getAbsolutePath() );

        // System.out.println("OUHHHHH " + resourceLoaderPath.getAbsolutePath());

        // props.setProperty( VelocityEngine.RESOURCE_LOADER, "classpath" );
        // props.setProperty( "classpath." + VelocityEngine.RESOURCE_LOADER + ".class",
        //                   ClasspathResourceLoader.class.getName() );
        try
        {
            //initialise the Velocity engine
            engine.setProperty( "runtime.log.logsystem", new NullLogSystem() );
            engine.init( props );
        }
        catch ( Exception e )
        {
            IllegalArgumentException iae = new IllegalArgumentException( "Could not initialise Velocity" );
            iae.initCause( e );
            throw iae;
        }
        //set the template
        if ( ! engine.templateExists( inputFileTemplatePath ) )
        {
            System.out.println( "Template not found!! ");
        }
        try
        {
            this.template = engine.getTemplate( inputFileTemplatePath );
        }
        catch ( Exception e )
        {
            IllegalArgumentException iae =
                new IllegalArgumentException( "Could not load the template file from '" + inputFileTemplatePath + "'" );
            iae.initCause( e );
            throw iae;
        }
    }

    public void generate()
        throws Exception
    {
        VelocityContext context = createContext();

        context.put( "dependencies", getDependenciesText( config ) );

        // I don't think we really need this anymore. Let's reenable it when really required.
        /*
        if ( config.getJnlp().getCodebase() != null ) {
            context.put( "codebase", config.getJnlp().getCodebase() );
        }
        */
        /*
        if ( config.getVendor() != null ) {
            context.put( "vendor", config.getVendor() );
        }
        */

        context.put( "outputFile", outputFile.getName() );
        context.put( "mainClass", config.getJnlp().getMainClass() );
        FileWriter writer = new FileWriter( outputFile );
        try
        {
            //parse the template
            //StringWriter writer = new StringWriter();
            template.merge( context, writer );
            writer.flush();
        }
        catch ( Exception e )
        {
            throw new Exception( "Could not generate the template " + template.getName() + ": " + e.getMessage(), e );
        }
        finally
        {
            writer.close();
        }
    }

    static String getDependenciesText( AbstractJnlpMojo config )
    {
        String dependenciesText = "";
        List artifacts = config.getPackagedJnlpArtifacts();
        if ( artifacts.size() != 0 )
        {
            StringBuffer buffer = new StringBuffer( 100 * artifacts.size() );
            buffer.append( "\n" );
            for ( int i = 0; i < artifacts.size(); i++ )
            {
                Artifact artifact = (Artifact) artifacts.get( i );
                buffer.append( "<jar href=\"" ).append( artifact.getFile().getName() ).append( "\"" );
                if ( config.isArtifactWithMainClass( artifact ) )
                {
                    buffer.append( " main=\"true\"" );
                }
                buffer.append( "/>\n" );
            }
            dependenciesText = buffer.toString();
        }
        return dependenciesText;
    }

    /**
     * @return Returns a velocity context with system and maven properties added
     */
    private VelocityContext createContext() {
        VelocityContext context = new VelocityContext();

        context.put( "dependencies", getDependenciesText( config ) );

        MavenProject project = config.getProject();
        
        addPropertiesToContext( System.getProperties(), context );
        addPropertiesToContext( project.getProperties(), context );
     
        context.put( "project", project.getModel() );

        // aliases named after the JNLP file structure
        context.put( "informationTitle", project.getModel().getName() );
        context.put( "informationDescription", project.getModel().getDescription() );
        context.put( "informationVendor", project.getModel().getOrganization().getName() );
        context.put( "informationHomepage", project.getModel().getOrganization().getUrl() );

        return context;
    }

    private static void addPropertiesToContext( Properties properties, VelocityContext context ) {
        for ( Iterator iter = properties.keySet().iterator(); iter.hasNext(); ) {
            String nextKey = (String) iter.next();
            String nextValue = properties.getProperty( nextKey );
            context.put( nextKey, nextValue );
        }
    }
}

@@ -5843,24 +5843,153 @@
 tProject();%0A
+%0A        // Note: properties that contain dots will not be properly parsed by Velocity. Should we replace dots with underscores ?
         %0A   

Add some code doc.