/* ==========================================================================
 * Copyright 2003-2004 Mevenide Team
 *
 * 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.
 * =========================================================================
 */
package org.netbeans.nbm;

import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
//import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.shared.filtering.MavenFilteringException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.filtering.MavenResourcesExecution;
import org.apache.maven.shared.filtering.MavenResourcesFiltering;
import org.netbeans.nbm.model.NbmResource;
import org.netbeans.nbm.model.NetBeansModule;
import org.netbeans.nbm.utils.ExamineManifest;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.taskdefs.Jar;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.PatternSet;
import org.apache.tools.ant.util.FileUtils;
import org.netbeans.nbbuild.CreateModuleXML;
import org.netbeans.nbbuild.MakeListOfNBM;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.netbeans.nbbuild.JHIndexer;

/**
 * Create the NetBeans module directory structure, a prerequisite for nbm creation and cluster creation.
 * 
 *
 * @author <a href="mailto:mkleint@codehaus.org">Milos Kleint</a>
 *
 */
public abstract class CreateNetBeansFileStructure
        extends AbstractNbmMojo
{

    /**
     * NetBeans module assembly build directory.
     * directory where the the NetBeans jar and nbm file get constructed.
     */
    @Parameter(defaultValue="${project.build.directory}/nbm", property="maven.nbm.buildDir")
    protected File nbmBuildDir;
    /**
     * Build directory
     */
    @Parameter(required=true, readonly=true, property="project.build.directory")
    protected File buildDir;
    /**
     * Name of the jar packaged by the jar:jar plugin
     */
    @Parameter(alias="jarname", property="project.build.finalName")
    protected String finalName;
    /**
     * a NetBeans module descriptor containing dependency information and more..
     * @deprecated all content from the module descriptor can be defined as plugin configuration now, will be removed in 4.0 entirely
     */
    @Parameter(defaultValue="${basedir}/src/main/nbm/module.xml")
    protected File descriptor;
    /**
     * NetBeans module's cluster. Replaces the cluster element in module descriptor.
     *
     */
    @Parameter(required=true, defaultValue="extra")
    protected String cluster;
    /**
     * The location of JavaHelp sources for the project. The documentation
     * itself is expected to be in the directory structure based on codenamebase of the module.
     * eg. if your codenamebase is "org.netbeans.modules.apisupport", then the actual docs
     * files shall go to ${basedir}/src/main/javahelp/org/netbeans/modules/apisupport/docs.
     * @deprecated Obsolete as of NetBeans 7.0 with &#64;HelpSetRegistration.
     * @since 2.7
     */
    @Deprecated
    @Parameter(defaultValue="${basedir}/src/main/javahelp")
    protected File nbmJavahelpSource;

    @Parameter(required=true, readonly=true, property="project")
    protected MavenProject project;

    /**
     * A list of additional resources to include in the NBM file.
     * (Not in the module JAR; see <code>InstalledFileLocator</code> for retrieval.)
     * Supersedes similarly-named configuration in the module descriptor file.
     * <p>For example, to include native libraries:</p>
     *
     <pre>
            &lt;nbmResource&gt;
            &nbsp;&nbsp;&lt;directory&gt;src/main/libs&lt;/directory&gt;
            &nbsp;&nbsp;&lt;targetPath&gt;modules/lib&lt;/targetPath&gt;
            &nbsp;&nbsp;&lt;includes&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&lt;include&gt;*.dll&lt;/include&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&lt;include&gt;*.so&lt;/include&gt;
            &nbsp;&nbsp;&lt;/includes&gt;
            &lt;/nbmResource&gt;
     </pre>
     *
     * @since 3.2
     */
    @Parameter
    protected Resource[] nbmResources;

    /**
     * The character encoding scheme to be applied when filtering nbm resources.
     *
     * @since 3.2
     */
    @Parameter(property="encoding", defaultValue="${project.build.sourceEncoding}")
    
    protected String encoding;
    
    /**
     * Deployment type of the module, allowed values are <code>normal</code>,<code>eager</code>,<code>autoload</code>,
     * <code>disabled</code>.
     * <p>
     * <code>autoload</code> - Such a module is
     * automatically enabled when some other module requires it and
     * automatically disabled otherwise.</p>
     *                     <p><code>eager</code> - This module type gets
     * automatically enabled when all it's dependencies are
     * satisfied. Disabled otherwise.</p>
     *                     <p><code>normal</code> - This is the default
     * value. This kind of module is enabled/disabled manually by
     * the user. It installs enabled.</p>
     *                     <p><code>disabled</code> - This kind of module is enabled/disabled manually by
     * the user. It installs disabled. Since 3.11</p>
     *
     * For details, see <a href="http://bits.netbeans.org/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#enablement">Netbeans Module system docs</a>
     *
     * Since 3.14, for autoload and eager modules, we automatically set AutoUpdate-Show-In-Client manifest entry to false, if not defined already otherwise in the manifest.
     * See issue <a href="http://jira.codehaus.org/browse/MNBMODULE-194">MNBMODULE-194</a>
     *
     * 
     * @since 3.8
     */ 
    @Parameter(defaultValue="normal")
    protected String moduleType;
    
    /**
     * codename base of the module, uniquely identifying the module within the NetBeans runtime. usually the package name equivalent.
     * Can include the major release version.
     * See <a href="http://bits.netbeans.org/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#how-manifest"> NetBeans Module system docs</a>
     * @since 3.8
     */
    @Parameter(defaultValue="${project.groupId}.${project.artifactId}")
    private String codeNameBase;
    
    /**
     * list of groupId:artifactId pairs describing libraries that go into the nbm file and will only include the .external reference in the nbm
     * instead of the actual binary. See <a href="http://netbeans.org/bugzilla/show_bug.cgi?id=195041">NetBeans issue #195041</a> for details.
     * Please note that the scheme will only work for artifacts present in central repository but no effort is made at build time to enforce that.
     * Additionally at runtime when installing the module, the user has to be online and be capable of reaching central using maven. 
     * You have been warned.
     * @since 3.8
     */ 
    @Parameter
    private List<String> externals;


    @Component
    protected MavenResourcesFiltering mavenResourcesFiltering;

    @Parameter(property="session", readonly=true, required=true)
    protected MavenSession session;


    //items used by the CreateNBMMojo.
    protected Project antProject;
    protected NetBeansModule module;
    protected File clusterDir;
    protected String moduleJarName;

    public void execute()
            throws MojoExecutionException, MojoFailureException
    {
        antProject = registerNbmAntTasks();
        if ( descriptor != null && descriptor.exists() )
        {
            module = readModuleDescriptor( descriptor );
        } else
        {
            module = createDefaultDescriptor( project, false );
        }
        //same moduleType related code in NetBeansManifestUpdateMojo.java
        String type = moduleType;
        if ("normal".equals(type) && module.getModuleType() != null) {
            type = module.getModuleType();
            getLog().warn( "moduleType in module descriptor is deprecated, use the plugin's parameter moduleType");
        }
        if (!"normal".equals(type) && !"autoload".equals(type) && !"eager".equals(type) && !"disabled".equals(type)) {
            getLog().error( "Only 'normal,autoload,eager,disabled' are allowed values in the moduleType parameter");
        }
        boolean autoload = "autoload".equals( type );
        boolean eager = "eager".equals( type );
        boolean disabled = "disabled".equals( type );
        // 1. initialization
        String moduleName = codeNameBase;
        if (module.getCodeNameBase() != null) {
            moduleName = module.getCodeNameBase();
            getLog().warn( "codeNameBase in module descriptor is deprecated, use the plugin's parameter codeNameBase");
        }
        moduleName = NetBeansManifestUpdateMojo.stripVersionFromCodebaseName( moduleName.replaceAll( "-", "." ) );
        moduleJarName = moduleName.replace( '.', '-' );
        if ( "extra".equals( cluster ) && module.getCluster() != null )
        {
            getLog().warn(
                    "Parameter cluster in module descriptor is deprecated, use the plugin configuration element." );
            cluster = module.getCluster();
        }
        File jarFile = new File( buildDir, finalName + ".jar" );
        clusterDir = new File( nbmBuildDir, "netbeans" + File.separator + cluster );
        File moduleJarLocation = new File( clusterDir, "modules" );
        moduleJarLocation.mkdirs();

        //2. create nbm resources
        File moduleFile = new File( moduleJarLocation, moduleJarName + ".jar" );

        try
        {
            boolean needPlainCopy = false;
            InputStream is = new FileInputStream( jarFile );
            try
            {
                JarInputStream jis = new JarInputStream( is );
                Manifest m = jis.getManifest();
                Attributes a = m.getMainAttributes();
                String classPath = ( String ) a.remove( new Attributes.Name( "X-Class-Path" ) );
                if ( classPath == null )
                {
                    needPlainCopy = true;
                }
                else // MNBMODULE-133
                {
                    getLog().info( "Copying module JAR to " + moduleJarLocation + " with manifest updates" );
                    a.putValue( "Class-Path", classPath );
                    a.remove( new Attributes.Name( "Maven-Class-Path" ) );
                    OutputStream os = new FileOutputStream( moduleFile );
                    try
                    {
                        JarOutputStream jos = new JarOutputStream( os, m );
                        JarEntry entry;
                        while ( ( entry = jis.getNextJarEntry() ) != null )
                        {
                            JarEntry entry2 = new JarEntry( entry );
                            jos.putNextEntry( entry2 );
                            int c;
                            while ( ( c = jis.read() ) != -1 )
                            {
                                jos.write( c );
                            }
                            jos.closeEntry();
                        }
                        jos.finish();
                        jos.close();
                    }
                    finally
                    {
                        os.close();
                    }
                }
            }
            finally
            {
                is.close();
            }
            if ( needPlainCopy )
            {
                getLog().info( "Copying module JAR to " + moduleJarLocation );
                FileUtils.getFileUtils().copyFile( jarFile, moduleFile, null, true, false );
            }
        }
        catch ( IOException x )
        {
            throw new MojoExecutionException( "Cannot copy module jar", x );
        }

        ExamineManifest modExaminator = new ExamineManifest( getLog() );
        modExaminator.setJarFile( moduleFile );
        modExaminator.checkFile();
        String classpathValue = modExaminator.getClasspath();

        if ( module != null )
        {
            // copy libraries to the designated place..
            @SuppressWarnings("unchecked")
            List<Artifact> artifacts = project.getRuntimeArtifacts();
            for ( Artifact artifact : artifacts )
            {
                File source = artifact.getFile();
                
                String path = NetBeansManifestUpdateMojo.artifactToClassPathEntry( artifact, codeNameBase );
                
                if ( classpathValue.contains( path ) )
                {
                    File target = new File( moduleJarLocation, path );

                    File targetDir = target.getParentFile();
                    targetDir.mkdirs();

                    try
                    {
                        FileUtils.getFileUtils().copyFile( source, target, null, true, false );
                        if ( externals != null && externals.contains(artifact.getGroupId() + ":" + artifact.getArtifactId())) // MNBMODULE-138
                        {
                            String name = target.getName();
                            getLog().info( "Using *.external replacement for " + name );
                            PrintWriter external = new PrintWriter( new File( targetDir, name + ".external" ), "UTF-8" );
                            try
                            {
                                writeExternal( external, artifact );
                            }
                            finally
                            {
                                external.close();
                            }
                        }
                    }
                    catch ( IOException ex )
                    {
                        getLog().error( "Cannot copy library jar" );
                        throw new MojoExecutionException( "Cannot copy library jar", ex );
                    }
                }
            }
            if ( nbmResources != null )
            {
                copyNbmResources();
            }
            copyDeprecatedNbmResources();
        }

        //javahelp stuff.
        if ( nbmJavahelpSource.exists() )
        {
            getLog().warn( "src/main/javahelp/ deprecated; use @HelpSetRegistration instead" );
            File javahelp_target = new File( buildDir, "javahelp" );
            String javahelpbase = moduleJarName.replace( '-', File.separatorChar ) + File.separator + "docs";
            String javahelpSearch = "JavaHelpSearch";
            File b = new File( javahelp_target, javahelpbase );
            File p = new File( b, javahelpSearch );
            p.mkdirs();
            Copy cp = (Copy) antProject.createTask( "copy" );
            cp.setTodir( javahelp_target );
            FileSet set = new FileSet();
            set.setDir( nbmJavahelpSource );
            cp.addFileset( set );
            cp.execute();
            getLog().info( "Generating JavaHelp Index..." );

            JHIndexer jhTask = (JHIndexer) antProject.createTask( "jhindexer" );
            jhTask.setBasedir( b );
            jhTask.setDb( p );
            jhTask.setIncludes( "**/*.html" );
            jhTask.setExcludes( javahelpSearch );
            Path path = new Path( antProject );
            jhTask.setClassPath( path );
            clearStaticFieldsInJavaHelpIndexer();
            try
            {
                jhTask.execute();
            }
            catch ( BuildException e )
            {
                getLog().error( "Cannot generate JavaHelp index." );
                throw new MojoExecutionException( e.getMessage(), e );
            }
            File helpJarLocation = new File( clusterDir, "modules/docs" );
            helpJarLocation.mkdirs();
            Jar jar = (Jar) antProject.createTask( "jar" );
            jar.setDestFile( new File( helpJarLocation, moduleJarName + ".jar" ) );
            set = new FileSet();
            set.setDir( javahelp_target );
            jar.addFileset( set );
            jar.execute();
        }

        File configDir = new File( clusterDir, "config" + File.separator + "Modules" );
        configDir.mkdirs();
        CreateModuleXML moduleXmlTask = (CreateModuleXML) antProject.createTask( "createmodulexml" );
        moduleXmlTask.setXmldir( configDir );
        FileSet fs = new FileSet();
        fs.setDir( clusterDir );
        fs.setIncludes( "modules" + File.separator + moduleJarName + ".jar" );
        if ( autoload )
        {
            moduleXmlTask.addAutoload( fs );
        }
        else if ( eager )
        {
            moduleXmlTask.addEager( fs );
        }
        else if ( disabled )
        {
            moduleXmlTask.addDisabled( fs );
        }
        else
        {
            moduleXmlTask.addEnabled( fs );
        }
        try
        {
            moduleXmlTask.execute();
        }
        catch ( BuildException e )
        {
            getLog().error( "Cannot generate config file." );
            throw new MojoExecutionException( e.getMessage(), e );
        }
        MakeListOfNBM makeTask = (MakeListOfNBM) antProject.createTask( "genlist" );
        antProject.setNewProperty( "module.name", finalName );
        antProject.setProperty( "cluster.dir", cluster );
        FileSet set = makeTask.createFileSet();
        set.setDir( clusterDir );
        PatternSet pattern = set.createPatternSet();
        pattern.setIncludes( "**" );
        makeTask.setModule( "modules" + File.separator + moduleJarName + ".jar" );
        makeTask.setOutputfiledir( clusterDir );
        try
        {
            makeTask.execute();
        }
        catch ( BuildException e )
        {
            getLog().error( "Cannot Generate nbm list" );
            throw new MojoExecutionException( e.getMessage(), e );
        }

    }

    private void copyDeprecatedNbmResources()
        throws BuildException, MojoExecutionException
    {
        // copy additional resources..
        List<NbmResource> ress = module.getNbmResources();
        if ( ress.size() > 0 )
        {
            getLog().warn( "NBM resources defined in module descriptor are deprecated. Please configure NBM resources in plugin configuration." );
            Copy cp = (Copy) antProject.createTask( "copy" );
            cp.setTodir( clusterDir );
            HashMap<File, Collection<FileSet>> customPaths = new HashMap<File, Collection<FileSet>>();
            boolean hasStandard = false;
            for ( NbmResource res : ress )
            {
                if ( res.getBaseDirectory() != null )
                {
                    File base = new File( project.getBasedir(), res.getBaseDirectory() );
                    FileSet set = new FileSet();
                    set.setDir( base );
                    for ( String inc : res.getIncludes() )
                    {
                        set.createInclude().setName( inc );
                    }
                    for ( String exc : res.getExcludes() )
                    {
                        set.createExclude().setName( exc );
                    }

                    if ( res.getRelativeClusterPath() != null )
                    {
                        File path = new File( clusterDir, res.getRelativeClusterPath() );
                        Collection<FileSet> col = customPaths.get( path );
                        if ( col == null )
                        {
                            col = new ArrayList<FileSet>();
                            customPaths.put( path, col );
                        }
                        col.add( set );
                    }
                    else
                    {
                        cp.addFileset( set );
                        hasStandard = true;
                    }
                }
            }
            try
            {
                if ( hasStandard )
                {
                    cp.execute();
                }
                if ( customPaths.size() > 0 )
                {
                    for ( Map.Entry<File, Collection<FileSet>> ent : customPaths.entrySet() )
                    {
                        cp = (Copy) antProject.createTask( "copy" );
                        cp.setTodir( ent.getKey() );
                        for ( FileSet set : ent.getValue() )
                        {
                            cp.addFileset( set );
                        }
                        cp.execute();
                    }
                }
            }
            catch ( BuildException e )
            {
                getLog().error( "Cannot copy additional resources into the nbm file" );
                throw new MojoExecutionException( e.getMessage(), e );
            }
        }
    }

    // repeated invokation of the javahelp indexer (possibly via multiple classloaders)
    // is causing trouble, residue from previous invokations seems to cause errors
    // this is a nasty workaround for the problem.
    // alternatively we could try invoking the indexer from a separate jvm i guess,
    // ut that's more work.
    private void clearStaticFieldsInJavaHelpIndexer() // MNBMODULE-51 hack
    {
        try
        {
            Class clazz = Class.forName( "com.sun.java.help.search.Indexer" );
            Field fld = clazz.getDeclaredField( "kitRegistry" );
            fld.setAccessible( true );
            Hashtable hash = (Hashtable) fld.get( null );
            hash.clear();

            clazz = Class.forName( "com.sun.java.help.search.HTMLIndexerKit" );
            fld = clazz.getDeclaredField( "defaultParser" );
            fld.setAccessible( true );
            fld.set( null, null);

            fld = clazz.getDeclaredField( "defaultCallback" );
            fld.setAccessible( true );
            fld.set( null, null);

        }
        catch ( IllegalArgumentException ex )
        {
            Logger.getLogger( CreateNetBeansFileStructure.class.getName() ).log( Level.SEVERE, null, ex );
        }
        catch ( IllegalAccessException ex )
        {
            Logger.getLogger( CreateNetBeansFileStructure.class.getName() ).log( Level.SEVERE, null, ex );
        }
        catch ( NoSuchFieldException ex )
        {
            Logger.getLogger( CreateNetBeansFileStructure.class.getName() ).log( Level.SEVERE, null, ex );
        }
        catch ( SecurityException ex )
        {
            Logger.getLogger( CreateNetBeansFileStructure.class.getName() ).log( Level.SEVERE, null, ex );
        }
        catch ( ClassNotFoundException ex )
        {
            Logger.getLogger( CreateNetBeansFileStructure.class.getName() ).log( Level.SEVERE, null, ex );
        }
    }

    private void copyNbmResources()
        throws MojoExecutionException
    {
        try
        {
            if ( StringUtils.isEmpty( encoding ) && isFilteringEnabled( nbmResources ) )
            {
                getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
                                   + ", i.e. build is platform dependent!" );
            }
            MavenResourcesExecution mavenResourcesExecution =
                new MavenResourcesExecution( Arrays.asList( nbmResources ), clusterDir, project, encoding,
                                             Collections.EMPTY_LIST, Collections.EMPTY_LIST, session );
            mavenResourcesExecution.setEscapeWindowsPaths( true );
            mavenResourcesFiltering.filterResources( mavenResourcesExecution );
        }
        catch ( MavenFilteringException ex )
        {
            throw new MojoExecutionException( ex.getMessage(), ex );
        }
    }

    /**
     * Determines whether filtering has been enabled for any resource.
     *
     * @param resources The set of resources to check for filtering.
     * @return <code>true</code> if at least one resource uses filtering, <code>false</code> otherwise.
     */
    private boolean isFilteringEnabled( Resource[] resources )
    {
        for ( Resource resource : resources )
        {
            if ( resource.isFiltering() )
            {
                return true;
            }
        }
        return false;
    }

    static void writeExternal( PrintWriter w, Artifact artifact )
        throws IOException
    {
        w.write( "CRC:" );
        File file = artifact.getFile();
        w.write( Long.toString( CreateClusterAppMojo.crcForFile( file ).getValue() ) );
        w.write( "\nSIZE:" );
        w.write( Long.toString( file.length() ) );
        w.write( "\nURL:m2:/" );
        w.write( artifact.getGroupId() );
        w.write( ':' );
        w.write( artifact.getArtifactId() );
        w.write( ':' );
        w.write( artifact.getVersion() );
        w.write( ':' );
        w.write( artifact.getType() );
        if ( artifact.getClassifier() != null )
        {
            w.write( ':' );
            w.write( artifact.getClassifier() );
        }
        w.write( "\nURL:" );
        // artifact.repository is null, so cannot use its url, and anyway might be a mirror
        w.write( /* M3: RepositorySystem.DEFAULT_REMOTE_REPO_URL + '/' */ "http://repo.maven.apache.org/maven2/" );
        w.write( new DefaultRepositoryLayout().pathOf( artifact ) );
        w.write( '\n' );
        w.flush();
    }

}
