package org.apache.maven.jxr;

/*
 * 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.
 */

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.TreeMap;

import org.apache.maven.jxr.pacman.ClassType;
import org.apache.maven.jxr.pacman.PackageManager;
import org.apache.maven.jxr.pacman.PackageType;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

/**
 * This class creates the navigational pages for jxr's cross-referenced source
 * files. The navigation is inspired by javadoc, so it should have a familiar feel.
 *
 * Creates the following files:
 * <ul>
 * <li><code>index.html</code>            main index containing the frameset</li>
 * <li><code>overview-frame.html</code>   list of the project's packages              (top left)</li>
 * <li><code>allclasses-frame.html</code> list of all classes in the project          (bottom left)</li>
 * <li><code>overview-summary.html</code> top-level listing of the project's packages (main frame)</li>
 *
 * <li>
 * Package specific:
 * <ul>
 * <li><code>package-summary.html</code> listing of all classes in this package    (main frame)</li>
 * <li><code>package-frame.html</code>   listing of all classes in this package    (bottom left)</li>
 * </ul>
 * </li>
 * </ul>
 *
 * @author <a href="mailto:bellingard@gmail.com">Fabrice Bellingard </a>
 * @author <a href="mailto:brian@brainslug.org">Brian Leonard</a>
 * @version $Id$
 */
public class DirectoryIndexer
{
    /*
     * JavaCodeTransform uses this to cross-reference package references
     * with that package's main summary page.
     */
    static final String INDEX = "package-summary.html";

    /*
     * Path to the root output directory.
     */
    private String root;

    /*
     * Package Manager for this project.
     */
    private PackageManager packageManager;

    /*
     * see the getter/setter docs for these properties
     */
    private String outputEncoding;

    private String templateDir;

    private String windowTitle;

    private String docTitle;

    private String bottom;

    /**
     * Constructor for the DirectoryIndexer object
     *
     * @param packageManager PackageManager for this project
     * @param root Path of the root output directory
     */
    public DirectoryIndexer( PackageManager packageManager, String root )
    {
        this.packageManager = packageManager;
        this.root = root;
    }

    /**
     * OutputEncoding is the encoding of output files.
     *
     * @param outputEncoding output Encoding
     */
    public void setOutputEncoding( String outputEncoding )
    {
        this.outputEncoding = outputEncoding;
    }

    /**
     * see setOutputEncoding(String)
     */
    public String getOutputEncoding()
    {
        return outputEncoding;
    }

    /**
     * TemplateDir is the location of the jelly template files used
     * to generate the navigation pages.
     *
     * @param templateDir location of the template directory
     */
    public void setTemplateDir( String templateDir )
    {
        this.templateDir = templateDir;
    }

    /**
     * see setTemplateDir(String)
     */
    public String getTemplateDir()
    {
        return templateDir;
    }

    /**
     * WindowTitle is used in the output's &lt;title&gt; tags
     * see the javadoc documentation for the property of the same name
     *
     * @param windowTitle the &lt;title&gt; attribute
     */
    public void setWindowTitle( String windowTitle )
    {
        this.windowTitle = windowTitle;
    }

    /**
     * see setWindowTitle(String)
     *
     * @see #setWindowTitle(String) setWindowTitle
     */
    public String getWindowTitle()
    {
        return windowTitle;
    }

    /**
     * DocTitle is used as a page heading for the summary files
     * see the javadoc documentation for the property of the same name
     *
     * @param docTitle major page heading
     */
    public void setDocTitle( String docTitle )
    {
        this.docTitle = docTitle;
    }

    /**
     * see setDocTitle(String)
     *
     * @see #setDocTitle(String) setDocTitle
     */
    public String getDocTitle()
    {
        return docTitle;
    }

    /**
     * Bottom is a footer for the navigation pages, usually a copyright
     * see the javadoc documentation for the property of the same name
     *
     * @param bottom page footer
     */
    public void setBottom( String bottom )
    {
        this.bottom = bottom;
    }

    /**
     * see setBottom(String)
     *
     * @see #setBottom(String) setBottom
     */
    public String getBottom()
    {
        return bottom;
    }

    /**
     * Does the actual indexing.
     *
     * @throws JxrException If something went wrong
     */
    public void process()
        throws JxrException
    {
        ProjectInfo info = getProjectInfo();

        VelocityEngine engine = new VelocityEngine();
        setProperties( engine );
        try
        {
            engine.init();
        }
        catch ( Exception e )
        {
            throw new JxrException( "Error initializing Velocity", e );
        }

        VelocityContext context = new VelocityContext();
        context.put( "outputEncoding", getOutputEncoding() );
        context.put( "windowTitle", getWindowTitle() );
        context.put( "docTitle", getDocTitle() );
        context.put( "bottom", getBottom() );
        context.put( "info", info );

        doVelocity( "index", root, context, engine );
        doVelocity( "overview-frame", root, context, engine );
        doVelocity( "allclasses-frame", root, context, engine );
        doVelocity( "overview-summary", root, context, engine );

        for ( PackageInfo pkgInfo : info.getAllPackages().values() )
        {
            VelocityContext subContext = new VelocityContext( context );
            subContext.put( "pkgInfo", pkgInfo );

            String outDir = root + '/' + pkgInfo.getDir();
            doVelocity( "package-summary", outDir, subContext, engine );
            doVelocity( "package-frame", outDir, subContext, engine );
        }
    }

    /*
     * Set Velocity properties to find templates
     */
    private void setProperties( VelocityEngine engine )
    {
        Path templateDirFile = Paths.get( getTemplateDir() );
        if ( templateDirFile.isAbsolute() )
        {
            // the property has been overridden: need to use a FileResourceLoader
            engine.setProperty( "resource.loader", "file" );
            engine.setProperty( "file.resource.loader.class",
                                "org.apache.velocity.runtime.resource.loader.FileResourceLoader" );
            engine.setProperty( "file.resource.loader.path", templateDirFile.toString() );
        }
        else
        {
            // use of the default templates
            engine.setProperty( "resource.loader", "classpath" );
            engine.setProperty( "classpath.resource.loader.class",
                                "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" );
        }
        // avoid "unable to find resource 'VM_global_library.vm' in any resource loader."
        engine.setProperty( "velocimacro.library", "" );
//        engine.setProperty( Log.class.getName(), log );
//        engine.setProperty( "runtime.log.logsystem.class", VelocityLogger.class.getName() );
    }

    /*
     * Generate the HTML file according to the Velocity template
     */
    private void doVelocity( String templateName, String outDir, VelocityContext context, VelocityEngine engine )
        throws JxrException
    {
        // output file
        File file = new File( outDir, templateName + ".html" );
        file.getParentFile().mkdirs();

        try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), getOutputEncoding() ) )
        {
            // template file
            StringBuilder templateFile = new StringBuilder();
            File templateDirFile = new File( getTemplateDir() );
            if ( !templateDirFile.isAbsolute() )
            {
                // default templates
                templateFile.append( getTemplateDir() );
                templateFile.append( '/' );
            }
            templateFile.append( templateName );
            templateFile.append( ".vm" );
            Template template = engine.getTemplate( templateFile.toString() );

            // do the merge
            template.merge( context, writer );
            writer.flush();
        }
        catch ( Exception e )
        {
            throw new JxrException( "Error merging velocity template", e );
        }
    }

    /*
     * Creates a Map of other Maps containing information about
     * this project's packages and classes, obtained from the PackageManager.
     *
     * allPackages collection of Maps with package info, with the following format
     *   {name}    package name (e.g., "org.apache.maven.jxr")
     *   {dir}     package dir relative to the root output dir (e.g., "org/apache/maven/jxr")
     *   {rootRef} relative link to root output dir (e.g., "../../../../") note trailing slash
     *   {classes} collection of Maps with class info
     *      {name}  class name (e.g., "DirectoryIndexer")
     *      {dir}   duplicate of package {dir}
     *
     * allClasses collection of Maps with class info, format as above
     *
     */
    ProjectInfo getProjectInfo()
    {
        Map<String, PackageInfo> allPackages = new TreeMap<>();
        Map<String, ClassInfo> allClasses = new TreeMap<>();

        for ( PackageType pkg : packageManager.getPackageTypes() )
        {
            String pkgName = pkg.getName();
            String pkgDir = pkgName.replace( '.', '/' );
            String rootRef = pkgName.replaceAll( "[^\\.]+(\\.|$)", "../" );

            // special case for the default package
            // javadoc doesn't deal with it, but it's easy for us
            if ( pkgName.length() == 0 )
            {
                pkgName = "(default package)";
                pkgDir = ".";
                rootRef = "./";
            }

            Map<String, ClassInfo> pkgClasses = new TreeMap<>();
            for ( ClassType clazz : pkg.getClassTypes() )
            {
                String className = clazz.getName();
                
                ClassInfo classInfo = new ClassInfo( className, pkgDir );
                
                classInfo.setFilename( clazz.getFilename() );

                pkgClasses.put( className, classInfo );
                
                // Adding package name to key in order to ensure classes with identical names in different packages are
                // all included.
                allClasses.put( className + "#" + pkgName, classInfo );
            }

            PackageInfo pkgInfo = new PackageInfo( pkgName, pkgDir );
            pkgInfo.setClasses( pkgClasses );
            pkgInfo.setRootRef( rootRef );

            allPackages.put( pkgName, pkgInfo );
        }

        return new ProjectInfo( allPackages, allClasses );
    }
    
    /**
     * 
     * @author Robert Scholte
     * @since 3.2.0
     */
    public static class ProjectInfo
    {
        private final Map<String, PackageInfo> allPackages;
        
        private final Map<String, ClassInfo> allClasses;

        public ProjectInfo( Map<String, PackageInfo> allPackages, Map<String, ClassInfo> allClasses )
        {
            this.allPackages = allPackages;
            this.allClasses = allClasses;
        }

        public Map<String, PackageInfo> getAllPackages()
        {
            return allPackages;
        }
        
        public Map<String, ClassInfo> getAllClasses()
        {
            return allClasses;
        }
    }
    
    /**
     * 
     * @author Robert Scholte
     * @since 3.2.0
     */
    public static class PackageInfo
    {
        private final String name;
        
        private final String dir;

        Map<String, ClassInfo> classes;
        
        private String rootRef;
        
        public PackageInfo( String name, String dir )
        {
            this.name = name;
            this.dir = dir;
        }
        
        public String getName()
        {
            return name;
        }
        
        public String getDir()
        {
            return dir;
        }
        
        public void setClasses( Map<String, ClassInfo> classes )
        {
            this.classes = classes;
        }
        
        public Map<String, ClassInfo> getClasses()
        {
            return classes;
        }
        
        public void setRootRef( String rootRef )
        {
            this.rootRef = rootRef;
        }
        
        public String getRootRef()
        {
            return rootRef;
        }
    }
    
    /**
     * Holds class information
     * 
     * @author Robert Scholte
     * @since 3.2.0
     */
    public static class ClassInfo
    {
        private final String name;
        
        private final String dir;
        
        private String filename;

        public ClassInfo( String name, String dir )
        {
            super();
            this.name = name;
            this.dir = dir;
        }
        
        public String getName()
        {
            return name;
        }
        
        public String getDir()
        {
            return dir;
        }
        
        public void setFilename( String filename )
        {
            this.filename = filename;
        }
        
        public String getFilename()
        {
            return filename;
        }
    }
}