package org.apache.maven.doxia.siterenderer;

/*
 * 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.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.maven.doxia.Doxia;
import org.apache.maven.doxia.logging.PlexusLoggerWrapper;
import org.apache.maven.doxia.sink.render.RenderingContext;
import org.apache.maven.doxia.parser.ParseException;
import org.apache.maven.doxia.parser.Parser;
import org.apache.maven.doxia.parser.manager.ParserNotFoundException;
import org.apache.maven.doxia.site.decoration.DecorationModel;
import org.apache.maven.doxia.module.site.SiteModule;
import org.apache.maven.doxia.module.site.manager.SiteModuleManager;
import org.apache.maven.doxia.module.site.manager.SiteModuleNotFoundException;
import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.Context;

import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.Os;
import org.codehaus.plexus.util.PathTool;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.velocity.SiteResourceLoader;
import org.codehaus.plexus.velocity.VelocityComponent;


/**
 * <p>DefaultSiteRenderer class.</p>
 *
 * @author <a href="mailto:evenisse@codehaus.org">Emmanuel Venisse</a>
 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 * @version $Id$
 * @since 1.0
 * @plexus.component role-hint="default"
 */
public class DefaultSiteRenderer
    extends AbstractLogEnabled
    implements Renderer
{
    // ----------------------------------------------------------------------
    // Requirements
    // ----------------------------------------------------------------------

    /**
     * @plexus.requirement
     */
    private VelocityComponent velocity;

    /**
     * @plexus.requirement
     */
    private SiteModuleManager siteModuleManager;

    /**
     * @plexus.requirement
     */
    private Doxia doxia;

    /**
     * @plexus.requirement
     */
    private I18N i18n;

    private static final String RESOURCE_DIR = "org/apache/maven/doxia/siterenderer/resources";

    private static final String DEFAULT_TEMPLATE = RESOURCE_DIR + "/default-site.vm";

    private static final String SKIN_TEMPLATE_LOCATION = "META-INF/maven/site.vm";

    // ----------------------------------------------------------------------
    // Renderer implementation
    // ----------------------------------------------------------------------

    /** {@inheritDoc} */
    public void render( Collection documents,
                        SiteRenderingContext siteRenderingContext,
                        File outputDirectory )
            throws RendererException, IOException
    {
        renderModule( documents, siteRenderingContext, outputDirectory );

        for ( Iterator i = siteRenderingContext.getSiteDirectories().iterator(); i.hasNext(); )
        {
            File siteDirectory = (File) i.next();
            copyResources( siteRenderingContext, new File( siteDirectory, "resources" ), outputDirectory );
        }
    }

    /** {@inheritDoc} */
    public Map locateDocumentFiles( SiteRenderingContext siteRenderingContext )
            throws IOException, RendererException
    {
        Map files = new LinkedHashMap();
        Map moduleExcludes = siteRenderingContext.getModuleExcludes();

        for ( Iterator i = siteRenderingContext.getSiteDirectories().iterator(); i.hasNext(); )
        {
            File siteDirectory = (File) i.next();
            if ( siteDirectory.exists() )
            {
                for ( Iterator j = siteModuleManager.getSiteModules().iterator(); j.hasNext(); )
                {
                    SiteModule module = (SiteModule) j.next();

                    File moduleBasedir = new File( siteDirectory, module.getSourceDirectory() );

                    if ( moduleExcludes != null && moduleExcludes.containsKey( module.getParserId() ) )
                    {
                        addModuleFiles( moduleBasedir, module, (String) moduleExcludes.get( module.getParserId() ),
                                files );
                    }
                    else
                    {
                        addModuleFiles( moduleBasedir, module, null, files );
                    }
                }
            }
        }

        for ( Iterator i = siteRenderingContext.getModules().iterator(); i.hasNext(); )
        {
            ModuleReference module = (ModuleReference) i.next();

            try
            {
                if ( moduleExcludes != null && moduleExcludes.containsKey( module.getParserId() ) )
                {
                    addModuleFiles( module.getBasedir(), siteModuleManager.getSiteModule( module.getParserId() ),
                            (String) moduleExcludes.get( module.getParserId() ), files );
                }
                else
                {
                    addModuleFiles( module.getBasedir(), siteModuleManager.getSiteModule( module.getParserId() ), null,
                            files );
                }
            }
            catch ( SiteModuleNotFoundException e )
            {
                throw new RendererException( "Unable to find module: " + e.getMessage(), e );
            }
        }
        return files;
    }

    private void addModuleFiles( File moduleBasedir,
                                 SiteModule module,
                                 String excludes,
                                 Map files )
            throws IOException, RendererException
    {
        if ( moduleBasedir.exists() )
        {
            List allFiles = FileUtils.getFileNames( moduleBasedir, "**/*.*", excludes, false );

            String lowerCaseExtension = module.getExtension().toLowerCase( Locale.ENGLISH );
            List docs = new LinkedList( allFiles );
            // Take care of extension case
            for ( Iterator it = docs.iterator(); it.hasNext(); )
            {
                String name = it.next().toString().trim();

                if ( !name.toLowerCase( Locale.ENGLISH ).endsWith( "." + lowerCaseExtension ) )
                {
                    it.remove();
                }
            }

            List velocityFiles = new LinkedList( allFiles );
            // *.xml.vm
            for ( Iterator it = velocityFiles.iterator(); it.hasNext(); )
            {
                String name = it.next().toString().trim();

                if ( !name.toLowerCase( Locale.ENGLISH ).endsWith( lowerCaseExtension + ".vm" ) )
                {
                    it.remove();
                }
            }
            docs.addAll( velocityFiles );

            for ( Iterator k = docs.iterator(); k.hasNext(); )
            {
                String doc = k.next().toString().trim();

                RenderingContext context =
                        new RenderingContext( moduleBasedir, doc, module.getParserId(), module.getExtension() );

                // TODO: DOXIA-111: we need a general filter here that knows how to alter the context
                if ( doc.toLowerCase( Locale.ENGLISH ).endsWith( ".vm" ) )
                {
                    context.setAttribute( "velocity", "true" );
                }

                String key = context.getOutputName();
                key = StringUtils.replace( key, "\\", "/" );

                if ( files.containsKey( key ) )
                {
                    DocumentRenderer renderer = (DocumentRenderer) files.get( key );

                    RenderingContext originalContext = renderer.getRenderingContext();

                    File originalDoc = new File( originalContext.getBasedir(), originalContext.getInputName() );

                    throw new RendererException( "Files '" + module.getSourceDirectory() + File.separator + doc
                        + "' clashes with existing '" + originalDoc + "'." );
                }
                // -----------------------------------------------------------------------
                // Handle key without case differences
                // -----------------------------------------------------------------------
                for ( Iterator iter = files.entrySet().iterator(); iter.hasNext(); )
                {
                    Map.Entry entry = (Map.Entry) iter.next();
                    if ( entry.getKey().toString().equalsIgnoreCase( key ) )
                    {
                        DocumentRenderer renderer = (DocumentRenderer) files.get( entry.getKey() );

                        RenderingContext originalContext = renderer.getRenderingContext();

                        File originalDoc = new File( originalContext.getBasedir(), originalContext.getInputName() );

                        if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
                        {
                            throw new RendererException( "Files '" + module.getSourceDirectory() + File.separator
                                + doc + "' clashes with existing '" + originalDoc + "'." );
                        }

                        if ( getLogger().isWarnEnabled() )
                        {
                            getLogger().warn(
                                              "Files '" + module.getSourceDirectory() + File.separator + doc
                                                  + "' could clashes with existing '" + originalDoc + "'." );
                        }
                    }
                }

                files.put( key, new DoxiaDocumentRenderer( context ) );
            }
        }
    }

    private void renderModule( Collection docs,
                               SiteRenderingContext siteRenderingContext,
                               File outputDirectory )
            throws IOException, RendererException
    {
        for ( Iterator i = docs.iterator(); i.hasNext(); )
        {
            DocumentRenderer docRenderer = (DocumentRenderer) i.next();

            RenderingContext renderingContext = docRenderer.getRenderingContext();

            File outputFile = new File( outputDirectory, docRenderer.getOutputName() );

            File inputFile = new File( renderingContext.getBasedir(), renderingContext.getInputName() );

            boolean modified = false;
            if ( !outputFile.exists() || inputFile.lastModified() > outputFile.lastModified() )
            {
                modified = true;
            }

            if ( modified || docRenderer.isOverwrite() )
            {
                if ( !outputFile.getParentFile().exists() )
                {
                    outputFile.getParentFile().mkdirs();
                }

                if ( getLogger().isDebugEnabled() )
                {
                    getLogger().debug( "Generating " + outputFile );
                }

                Writer writer = null;
                try
                {
                    writer = WriterFactory.newWriter( outputFile, siteRenderingContext.getOutputEncoding() );
                    docRenderer.renderDocument( writer, this, siteRenderingContext );
                }
                finally
                {
                    IOUtil.close( writer );
                }
            }
            else
            {
                if ( getLogger().isDebugEnabled() )
                {
                    getLogger().debug( inputFile + " unchanged, not regenerating..." );
                }
            }
        }
    }

    /** {@inheritDoc} */
    public void renderDocument( Writer writer,
                                RenderingContext renderingContext,
                                SiteRenderingContext context )
            throws RendererException, FileNotFoundException, UnsupportedEncodingException
    {
        SiteRendererSink sink = new SiteRendererSink( renderingContext );

        File doc = new File( renderingContext.getBasedir(), renderingContext.getInputName() );

        Reader reader = null;
        try
        {
            Parser parser = doxia.getParser( renderingContext.getParserId() );

            // TODO: DOXIA-111: the filter used here must be checked generally.
            if ( renderingContext.getAttribute( "velocity" ) != null )
            {
                String resource = doc.getAbsolutePath();

                try
                {
                    SiteResourceLoader.setResource( resource );

                    Context vc = createContext( sink, context );

                    StringWriter sw = new StringWriter();

                    velocity.getEngine().mergeTemplate( resource, context.getInputEncoding(), vc, sw );

                    reader = new StringReader( sw.toString() );
                }
                catch ( Exception e )
                {
                    if ( getLogger().isDebugEnabled() )
                    {
                        getLogger().error( "Error parsing " + resource + " as a velocity template, using as text.", e );
                    }
                    else
                    {
                        getLogger().error( "Error parsing " + resource + " as a velocity template, using as text." );
                    }
                }
            }
            else
            {
                switch ( parser.getType() )
                {
                    case Parser.XML_TYPE:
                        reader = ReaderFactory.newXmlReader( doc );
                        break;

                    case Parser.TXT_TYPE:
                    case Parser.UNKNOWN_TYPE:
                    default:
                        reader = ReaderFactory.newReader( doc, context.getInputEncoding() );
                }
            }
            sink.enableLogging( new PlexusLoggerWrapper( getLogger() ) );
            doxia.parse( reader, renderingContext.getParserId(), sink );
        }
        catch ( ParserNotFoundException e )
        {
            throw new RendererException( "Error getting a parser for '" + doc + "': " + e.getMessage(), e );
        }
        catch ( ParseException e )
        {
            throw new RendererException( "Error parsing '"
                    + doc + "': line [" + e.getLineNumber() + "] " + e.getMessage(), e );
        }
        catch ( IOException e )
        {
            throw new RendererException( "IOException when processing '" + doc + "'", e );
        }
        finally
        {
            sink.flush();

            sink.close();

            IOUtil.close( reader );
        }

        generateDocument( writer, sink, context );
    }

    private Context createContext( SiteRendererSink sink,
                                   SiteRenderingContext siteRenderingContext )
    {
        VelocityContext context = new VelocityContext();

        // ----------------------------------------------------------------------
        // Data objects
        // ----------------------------------------------------------------------

        RenderingContext renderingContext = sink.getRenderingContext();
        context.put( "relativePath", renderingContext.getRelativePath() );

        // Add infos from document
        context.put( "authors", sink.getAuthors() );

        String title = "";
        if ( siteRenderingContext.getDecoration().getName() != null )
        {
            title = siteRenderingContext.getDecoration().getName();
        }
        else if ( siteRenderingContext.getDefaultWindowTitle() != null )
        {
            title = siteRenderingContext.getDefaultWindowTitle();
        }

        if ( title.length() > 0 )
        {
            title += " - ";
        }
        title += sink.getTitle();

        context.put( "title", title );

        context.put( "headContent", sink.getHead() );

        context.put( "bodyContent", sink.getBody() );

        context.put( "decoration", siteRenderingContext.getDecoration() );

        SimpleDateFormat sdf = new SimpleDateFormat( "yyyyMMdd" );
        if ( StringUtils.isNotEmpty( sink.getDate() ) )
        {
            try
            {
                // we support only ISO-8601 date
                context.put( "dateCreation", sdf.format( new SimpleDateFormat( "yyyy-MM-dd" ).parse( sink.getDate() ) ) );
            }
            catch ( Exception e )
            {
                // nop
            }
        }
        context.put( "dateRevision", sdf.format( new Date() ) );

        context.put( "currentDate", new Date() );

        Locale locale = siteRenderingContext.getLocale();
        context.put( "dateFormat", DateFormat.getDateInstance( DateFormat.DEFAULT, locale ) );

        String currentFileName = renderingContext.getOutputName().replace( '\\', '/' );
        context.put( "currentFileName", currentFileName );

        context.put( "alignedFileName", PathTool.calculateLink( currentFileName, renderingContext.getRelativePath() ) );

        context.put( "locale", locale );

        // Add user properties
        Map templateProperties = siteRenderingContext.getTemplateProperties();

        if ( templateProperties != null )
        {
            for ( Iterator i = templateProperties.keySet().iterator(); i.hasNext(); )
            {
                String key = (String) i.next();

                context.put( key, templateProperties.get( key ) );
            }
        }

        // ----------------------------------------------------------------------
        // Tools
        // ----------------------------------------------------------------------

        context.put( "PathTool", new PathTool() );

        context.put( "FileUtils", new FileUtils() );

        context.put( "StringUtils", new StringUtils() );

        context.put( "i18n", i18n );

        return context;
    }

    /** {@inheritDoc} */
    public void generateDocument( Writer writer,
                                  SiteRendererSink sink,
                                  SiteRenderingContext siteRenderingContext )
            throws RendererException
    {
        Context context = createContext( sink, siteRenderingContext );

        writeTemplate( writer, context, siteRenderingContext );
    }

    private void writeTemplate( Writer writer,
                                Context context,
                                SiteRenderingContext siteContext )
            throws RendererException
    {
        ClassLoader old = null;

        if ( siteContext.getTemplateClassLoader() != null )
        {
            // -------------------------------------------------------------------------
            // If no template classloader was set we'll just use the context classloader
            // -------------------------------------------------------------------------

            old = Thread.currentThread().getContextClassLoader();

            Thread.currentThread().setContextClassLoader( siteContext.getTemplateClassLoader() );
        }

        try
        {
            processTemplate( siteContext.getTemplateName(), context, writer );
        }
        finally
        {
            IOUtil.close( writer );

            if ( old != null )
            {
                Thread.currentThread().setContextClassLoader( old );
            }
        }
    }

    /**
     * @noinspection OverlyBroadCatchBlock,UnusedCatchParameter
     */
    private void processTemplate( String templateName,
                                  Context context,
                                  Writer writer )
            throws RendererException
    {
        Template template;

        try
        {
            template = velocity.getEngine().getTemplate( templateName );
        }
        catch ( Exception e )
        {
            throw new RendererException( "Could not find the template '" + templateName, e );
        }

        try
        {
            template.merge( context, writer );
        }
        catch ( Exception e )
        {
            throw new RendererException( "Error while generating code.", e );
        }
    }

    /** {@inheritDoc} */
    public SiteRenderingContext createContextForSkin( File skinFile,
                                                      Map attributes,
                                                      DecorationModel decoration,
                                                      String defaultWindowTitle,
                                                      Locale locale )
            throws IOException
    {
        SiteRenderingContext context = new SiteRenderingContext();

        // TODO: plexus-archiver, if it could do the excludes
        ZipFile zipFile = new ZipFile( skinFile );
        try
        {
            if ( zipFile.getEntry( SKIN_TEMPLATE_LOCATION ) != null )
            {
                context.setTemplateName( SKIN_TEMPLATE_LOCATION );
                context.setTemplateClassLoader( new URLClassLoader( new URL[]{skinFile.toURI().toURL()} ) );
            }
            else
            {
                context.setTemplateName( DEFAULT_TEMPLATE );
                context.setTemplateClassLoader( getClass().getClassLoader() );
                context.setUsingDefaultTemplate( true );
            }
        }
        finally
        {
            closeZipFile( zipFile );
        }

        context.setTemplateProperties( attributes );
        context.setLocale( locale );
        context.setDecoration( decoration );
        context.setDefaultWindowTitle( defaultWindowTitle );
        context.setSkinJarFile( skinFile );

        return context;
    }

    /** {@inheritDoc} */
    public SiteRenderingContext createContextForTemplate( File templateFile,
                                                          File skinFile,
                                                          Map attributes,
                                                          DecorationModel decoration,
                                                          String defaultWindowTitle,
                                                          Locale locale )
            throws MalformedURLException
    {
        SiteRenderingContext context = new SiteRenderingContext();

        context.setTemplateName( templateFile.getName() );
        context.setTemplateClassLoader( new URLClassLoader( new URL[]{templateFile.getParentFile().toURI().toURL()} ) );

        context.setTemplateProperties( attributes );
        context.setLocale( locale );
        context.setDecoration( decoration );
        context.setDefaultWindowTitle( defaultWindowTitle );
        context.setSkinJarFile( skinFile );

        return context;
    }

    private void closeZipFile( ZipFile zipFile )
    {
        // TODO: move to plexus utils
        try
        {
            zipFile.close();
        }
        catch ( IOException e )
        {
            // ignore
        }
    }

    /** {@inheritDoc} */
    public void copyResources( SiteRenderingContext siteRenderingContext,
                               File resourcesDirectory,
                               File outputDirectory  )
            throws IOException
    {
        if ( siteRenderingContext.getSkinJarFile() != null )
        {
            // TODO: plexus-archiver, if it could do the excludes
            ZipFile file = new ZipFile( siteRenderingContext.getSkinJarFile() );
            try
            {
                for ( Enumeration e = file.entries(); e.hasMoreElements(); )
                {
                    ZipEntry entry = (ZipEntry) e.nextElement();

                    if ( !entry.getName().startsWith( "META-INF/" ) )
                    {
                        File destFile = new File( outputDirectory, entry.getName() );
                        if ( !entry.isDirectory() )
                        {
                            destFile.getParentFile().mkdirs();

                            copyFileFromZip( file, entry, destFile );
                        }
                        else
                        {
                            destFile.mkdirs();
                        }
                    }
                }
            }
            finally
            {
                file.close();
            }
        }

        if ( siteRenderingContext.isUsingDefaultTemplate() )
        {
            InputStream resourceList = getClass().getClassLoader()
                    .getResourceAsStream( RESOURCE_DIR + "/resources.txt" );

            if ( resourceList != null )
            {
                Reader r = null;
                try
                {
                    r = ReaderFactory.newReader( resourceList, ReaderFactory.UTF_8 );
                    LineNumberReader reader = new LineNumberReader( r );

                    String line = reader.readLine();

                    while ( line != null )
                    {
                        InputStream is = getClass().getClassLoader().getResourceAsStream( RESOURCE_DIR + "/" + line );

                        if ( is == null )
                        {
                            throw new IOException( "The resource " + line + " doesn't exist." );
                        }

                        File outputFile = new File( outputDirectory, line );

                        if ( !outputFile.getParentFile().exists() )
                        {
                            outputFile.getParentFile().mkdirs();
                        }

                        OutputStream os = null;
                        try
                        {
                            // for the images
                            os = new FileOutputStream( outputFile );
                            IOUtil.copy( is, os );
                        }
                        finally
                        {
                            IOUtil.close( os );
                        }

                        IOUtil.close( is );

                        line = reader.readLine();
                    }
                }
                finally
                {
                    IOUtil.close( r );
                }
            }
        }

        // Copy extra site resources
        if ( resourcesDirectory != null && resourcesDirectory.exists() )
        {
            copyDirectory( resourcesDirectory, outputDirectory );
        }

        // Check for the existence of /css/site.css
        File siteCssFile = new File( outputDirectory, "/css/site.css" );
        if ( !siteCssFile.exists() )
        {
            // Create the subdirectory css if it doesn't exist, DOXIA-151
            File cssDirectory = new File( outputDirectory, "/css/" );
            boolean created = cssDirectory.mkdirs();
            if ( created && getLogger().isDebugEnabled() )
            {
                getLogger().debug(
                    "The directory '" + cssDirectory.getAbsolutePath() + "' did not exist. It was created." );
            }

            // If the file is not there - create an empty file, DOXIA-86
            if ( getLogger().isDebugEnabled() )
            {
                getLogger().debug(
                    "The file '" + siteCssFile.getAbsolutePath() + "' does not exists. Creating an empty file." );
            }
            Writer writer = null;
            try
            {
                writer = WriterFactory.newWriter( siteCssFile, siteRenderingContext.getOutputEncoding() );
                //DOXIA-290...the file should not be 0 bytes.
                writer.write( "/* You can override this file with your own styles */"  );
            }
            finally
            {
                IOUtil.close( writer );
            }
        }
    }

    private void copyFileFromZip( ZipFile file,
                                  ZipEntry entry,
                                  File destFile )
            throws IOException
    {
        FileOutputStream fos = new FileOutputStream( destFile );

        try
        {
            IOUtil.copy( file.getInputStream( entry ), fos );
        }
        finally
        {
            IOUtil.close( fos );
        }
    }

    /**
     * Copy the directory
     *
     * @param source      source file to be copied
     * @param destination destination file
     * @throws java.io.IOException if any
     */
    protected void copyDirectory( File source,
                                  File destination )
            throws IOException
    {
        if ( source.exists() )
        {
            DirectoryScanner scanner = new DirectoryScanner();

            String[] includedResources = {"**/**"};

            scanner.setIncludes( includedResources );

            scanner.addDefaultExcludes();

            scanner.setBasedir( source );

            scanner.scan();

            List includedFiles = Arrays.asList( scanner.getIncludedFiles() );

            for ( Iterator j = includedFiles.iterator(); j.hasNext(); )
            {
                String name = (String) j.next();

                File sourceFile = new File( source, name );

                File destinationFile = new File( destination, name );

                FileUtils.copyFile( sourceFile, destinationFile );
            }
        }
    }

}
