/*
 *  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.myfaces.buildtools.maven2.plugin.builder;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.myfaces.buildtools.maven2.plugin.builder.model.Model;
import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.BuildException;
import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.MavenPluginConsoleLogSystem;
import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.MyfacesUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.Xpp3DomWriter;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

/**
 * Creates taglib (tld) and faces-config files.
 * <p>
 * This Mojo actually provides a generic goal that will run a configurable
 * velocity template file and generate a single output file. The template is
 * passed the full metadata model object, and can select from the model whatever
 * data it wants.
 * </p>
 * <p>
 * The execution can be configured with:
 * <ul>
 * <li>The name of the input template to be executed</li>
 * <li>The name of the output file to be created</li>
 * <li>Any number of variables which are accessable from the template
 * (string values only)</li>
 * </ul>
 * </p>
 * <p>
 * The executed template has the following variables available to it:
 * <ul>
 * <li>model: the full metadata model for this project</li>
 * <li>modelIds: specifies which items from the model should be processed</li>
 * <li>baseContent: the full text of the contents of the "xmlBaseFile" (if any)</li>
 * <li>utils: an instance of MyfacesUtils that provides static helper methods</li>
 * <li>and whatever (name,value) pairs were configured via the "params" property
 * of this mojo.</li>
 * </ul>
 * </p>
 * 
 * @requiresDependencyResolution compile
 * @goal make-config
 * @phase generate-sources
 */
public class MakeConfigMojo extends AbstractBuilderMojo
{
    /**
     * The current maven project (auto-injected by Maven).
     * 
     * @parameter expression="${project}"
     * @readonly
     */
    private MavenProject project;

    /**
     * Defines the directory where the metadata file (META-INF/myfaces-metadata.xml) is loaded,
     * and the generated file named by xmlFile parameter is created. 
     * 
     * @parameter expression="${project.build.directory}/generated-resources/myfaces-builder-plugin"
     */
    private File buildDirectory;

    /**
     * Defines the directory where the resource will be output. 
     * 
     * @since 1.0.4
     * @parameter expression="${project.build.directory}/generated-resources/myfaces-builder-plugin"
     */
    private File outputDirectory;
    
    /**
     * Name of the file from which the metadata model passed to the
     * template will be read. This file is typically generated by an earlier
     * execution of the BuildMetaDataMojo goal for the same maven project.
     * 
     * @parameter
     */
    private String metadataFile = "META-INF/myfaces-metadata.xml";

    /**
     * Specifies the name of the output file to be created.
     * 
     * @parameter
     */
    private String xmlFile = "META-INF/faces-config.xml";
    
    /**
     * A list of metadata model ids.
     * <p>
     * If not defined, then this defaults to a list containing just one string whose
     * value is the same as the current maven project's artifactId.
     * </p>
     * <p>
     * The complete metadata model is passed to the velocity template. This contains 
     * data about not just the model items defined in the calling project, but also
     * about items imported from other projects. Each item in the model is
     * labelled with a "model id" indicating which project it was defined by.
     * </p>
     * <p>
     * This list of model ids is also passed to the template. The template can
     * then use that data to select the relevant items from the full model.
     * </p>
     * 
     * @parameter
     */
    private List modelIds;
            
    /**
     * The base directory used when resolving references to external files from
     * velocity #include and #parse commands within the executed template.
     * 
     * @parameter expression="src/main/resources/META-INF"
     */
    private File templateSourceDirectory;
    
    /**
     * When defined, specifies an xml file whose top-level elements are to be copied
     * directly into the created file.
     * <p>
     * This allows a hand-written file to be created containing data that cannot be
     * automatically generated. All content beneath the root element of the specified
     * file (but not the root element itself) is placed into a Velocity variable
     * named "baseContent" that the template can reference.
     * </p>
     * <p>
     * The template can do whatever it wants with this variable, but it is expected
     * that the template will simply output this immediately after writing the
     * root element of the output xml file.
     * file.
     * </p>
     * <p>
     * Note that any attributes or namespaces defined on the root element of the
     * xmlBaseFile are ignored.
     * </p>
     * 
     * @parameter expression="src/main/conf/META-INF/faces-config-base.xml"
     */    
    private File xmlBaseFile;

    /**
     * Specifies the Velocity template file to be executed.
     * 
     * @parameter expression="faces-config11.vm"
     */
    private String templateFile;
    
    /**
     * A map of (name, value) pairs to be made available as Velocity variables
     * for the executed template to access.
     * 
     * @parameter
     */
    private Map params;
        
    /**
     * Execute the Mojo.
     * <p>
     * The metadata model is loaded, and the specified template is executed with
     * any template output being written to the specified output file.
     * </p>
     */
    public void execute() throws MojoExecutionException
    {
        try
        {
            if (modelIds == null)
            {
                modelIds = new ArrayList();
                modelIds.add(project.getArtifactId());
            }

            // Load the metadata file from an xml file (presumably generated
            // by an earlier execution of the build-metadata goal.
            File mdFile = new File(buildDirectory, metadataFile);
            Model model = IOUtils.loadModel(mdFile);

            // Flatten the model so that the template can access every property
            // of each model item directly, even when the property is actually
            // defined on an ancestor class or interface.
            new Flattener(model).flatten();
            
            Properties cacheInfo = new Properties();
            loadCache(cacheInfo);
            generateConfigFromVelocity(model, cacheInfo, mdFile.lastModified() );
            storeCache(cacheInfo);
        }
        catch (IOException e)
        {
            throw new MojoExecutionException("Error during config generation", e);
        }
        catch (BuildException e)
        {
            throw new MojoExecutionException("Error during config generation", e);
        }
    }
    
    private void generateConfigFromVelocity(Model model,
        Properties cachedInfo, long lastModifiedMetadata) throws IOException,
        MojoExecutionException
    {    
        Writer writer = null;
        File outFile = null;
        File tf = new File(templateSourceDirectory, templateFile);
        
        try
        {
            outFile = new File(outputDirectory, xmlFile);

            if ( !outFile.getParentFile().exists() )
            {
                outFile.getParentFile().mkdirs();
            }
            
            if (isCachingEnabled() && outFile.exists())
            {
                boolean upToDate = isFileUpToDate(cachedInfo, lastModifiedMetadata, outFile); 
                
                if (upToDate && xmlBaseFile != null && xmlBaseFile.exists())
                {
                    upToDate = isFileUpToDate(cachedInfo, xmlBaseFile);
                }
                if (upToDate && tf != null && tf.exists())
                {
                    upToDate = isFileUpToDate(cachedInfo, tf);
                }
                
                if (upToDate)
                {
                    getLog().info("generated file " +outFile.getName()+ " is up to date");
                    return;
                }
            }
            
            VelocityEngine velocityEngine = initVelocity();

            VelocityContext baseContext = new VelocityContext();
            baseContext.put("utils", new MyfacesUtils());
            
            String baseContent = "";
            
            if (xmlBaseFile != null && xmlBaseFile.exists())
            {
                getLog().info("using base content file: "+xmlBaseFile.getPath());
                
                Reader reader = null;
                try
                {
                    reader = new FileReader(xmlBaseFile);
                    Xpp3Dom root = Xpp3DomBuilder.build(reader);
                    
                    StringWriter swriter = new StringWriter();
                    
                    Xpp3Dom [] children = root.getChildren();
                    
                    for (int i = 0; i< children.length; i++)
                    {
                        Xpp3Dom dom = children[i];
                        Xpp3DomWriter.write(swriter, dom);
                        swriter.write('\n');
                    }
                    baseContent = swriter.toString();
                    swriter.close();
                }
                catch (XmlPullParserException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                finally
                {
                    reader.close();
                }
            }
            
            baseContext.put("baseContent", baseContent);
            
            baseContext.put("model", model);
            
            baseContext.put("modelIds", modelIds);
            
            if (params != null)
            {
                //Load all parameters to the context, so the template can
                //load it. This allow to generate any config file we want
                //(faces-config, tld, facelet,....)
                for (Iterator it = params.keySet().iterator(); it.hasNext();)
                {
                    String key = (String) it.next();
                    baseContext.put(key,params.get(key));
                }
            }
            
            writer = new OutputStreamWriter(new FileOutputStream(outFile));
            
            Template template = velocityEngine.getTemplate(templateFile);
            
            template.merge(baseContext, writer);

            writer.flush();
            
            if (isCachingEnabled())
            {
                cachedInfo.put(outFile.getAbsolutePath(), Long.toString(lastModifiedMetadata));
                if (xmlBaseFile != null && xmlBaseFile.exists())
                {
                    cachedInfo.put(xmlBaseFile.getAbsolutePath(), Long.toString(xmlBaseFile.lastModified()));
                }
                if (tf != null && tf.exists())
                {
                    cachedInfo.put(tf.getAbsolutePath(), Long.toString(tf.lastModified()));
                }
            }
        }
        catch (ResourceNotFoundException e)
        {
            throw new MojoExecutionException(
                    "Error merging velocity templates: " + e.getMessage(), e);
        }
        catch (ParseErrorException e)
        {
            throw new MojoExecutionException(
                    "Error merging velocity templates: " + e.getMessage(), e);
        }
        catch (Exception e)
        {
            throw new MojoExecutionException(
                    "Error merging velocity templates: " + e.getMessage(), e);
        }
        finally
        {
            IOUtil.close(writer);
            writer = null;
        }        
    }

    private VelocityEngine initVelocity() throws MojoExecutionException
    {
        VelocityEngine velocityEngine = new VelocityEngine();
                
        try
        {
            velocityEngine.setProperty( "resource.loader", "file, class" );
            velocityEngine.setProperty( "file.resource.loader.class",
                    "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
            velocityEngine.setProperty( "file.resource.loader.path", templateSourceDirectory.getPath());
            velocityEngine.setProperty( "class.resource.loader.class",
                    "org.apache.myfaces.buildtools.maven2.plugin.builder.utils.RelativeClasspathResourceLoader" );
            velocityEngine.setProperty( "class.resource.loader.path", "META-INF");            
            velocityEngine.setProperty( "velocimacro.library", "xmlMacros.vm");
            velocityEngine.setProperty( "velocimacro.permissions.allow.inline","true");
            velocityEngine.setProperty( "velocimacro.permissions.allow.inline.local.scope", "true");
            velocityEngine.setProperty( "directive.foreach.counter.initial.value","0");
            //velocityEngine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
            //"org.apache.myfaces.buildtools.maven2.plugin.builder.utils.ConsoleLogSystem" );

            velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM,
                    new MavenPluginConsoleLogSystem(this.getLog()));

            velocityEngine.init();
        }
        catch (Exception e)
        {
            throw new MojoExecutionException("Error creating VelocityEngine", e);
        }
        
        return velocityEngine;
    }
    
}
