package org.apache.maven.doxia.docrenderer.pdf.itext;

/*
 * 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.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.maven.doxia.docrenderer.DocumentRendererException;
import org.apache.maven.doxia.docrenderer.pdf.AbstractPdfRenderer;
import org.apache.maven.doxia.document.DocumentCover;
import org.apache.maven.doxia.document.DocumentMeta;
import org.apache.maven.doxia.document.DocumentModel;
import org.apache.maven.doxia.document.DocumentTOCItem;
import org.apache.maven.doxia.module.itext.ITextSink;
import org.apache.maven.doxia.module.itext.ITextSinkFactory;
import org.apache.maven.doxia.module.itext.ITextUtil;
import org.apache.maven.doxia.module.site.SiteModule;
import org.apache.xml.utils.DefaultErrorHandler;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import com.lowagie.text.ElementTags;

/**
 * Abstract <code>document</code> render with the <code>iText</code> framework
 *
 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 * @author ltheussl
 * @version $Id$
 * @since 1.1
 * @plexus.component role="org.apache.maven.doxia.docrenderer.pdf.PdfRenderer" role-hint="itext"
 */
public class ITextPdfRenderer
    extends AbstractPdfRenderer
{
    /** The xslt style sheet used to transform a Document to an iText file. */
    private static final String XSLT_RESOURCE = "TOC.xslt";

    /** The TransformerFactory. */
    private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();

    /** The DocumentBuilderFactory. */
    private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();

    /** The DocumentBuilder. */
    private static final DocumentBuilder DOCUMENT_BUILDER;

    static
    {
        TRANSFORMER_FACTORY.setErrorListener( new DefaultErrorHandler() );

        try
        {
            DOCUMENT_BUILDER = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder();
        }
        catch ( ParserConfigurationException e )
        {
            throw new RuntimeException( "Error building document :" + e.getMessage() );
        }
    }

    /** {@inheritDoc} */
    public void generatePdf( File inputFile, File pdfFile )
        throws DocumentRendererException
    {
        if ( getLogger().isDebugEnabled() )
        {
            getLogger().debug( "Generating : " + pdfFile );
        }

        try
        {
            ITextUtil.writePdf( new FileInputStream( inputFile ), new FileOutputStream( pdfFile ) );
        }
        catch ( IOException e )
        {
            throw new DocumentRendererException( "Cannot create PDF from " + inputFile + ": " + e.getMessage(), e );
        }
        catch ( RuntimeException e )
        {
            throw new DocumentRendererException( "Error creating PDF from " + inputFile + ": " + e.getMessage(), e );
        }
    }

    /** {@inheritDoc} */
    public void render( Map filesToProcess, File outputDirectory, DocumentModel documentModel )
        throws DocumentRendererException, IOException
    {
        // copy resources, images, etc.
        copyResources( outputDirectory );

        if ( documentModel == null )
        {
            getLogger().debug( "No document model, generating all documents individually." );

            renderIndividual( filesToProcess, outputDirectory );
            return;
        }

        String outputName = getOutputName( documentModel );

        File outputITextFile = new File( outputDirectory, outputName + ".xml" );
        if ( !outputITextFile.getParentFile().exists() )
        {
            outputITextFile.getParentFile().mkdirs();
        }

        File pdfOutputFile = new File( outputDirectory, outputName + ".pdf" );
        if ( !pdfOutputFile.getParentFile().exists() )
        {
            pdfOutputFile.getParentFile().mkdirs();
        }

        List iTextFiles;
        if ( ( documentModel.getToc() == null ) || ( documentModel.getToc().getItems() == null ) )
        {
            getLogger().info( "No TOC is defined in the document descriptor. Merging all documents." );

            iTextFiles = parseAllFiles( filesToProcess, outputDirectory );
        }
        else
        {
            getLogger().debug( "Using TOC defined in the document descriptor." );

            iTextFiles = parseTOCFiles( filesToProcess, outputDirectory, documentModel );
        }

        File iTextFile = new File( outputDirectory, outputName + ".xml" );
        File iTextOutput = new File( outputDirectory, outputName + "." + getOutputExtension() );
        Document document = generateDocument( iTextFiles );
        transform( documentModel, document, iTextFile );
        generatePdf( iTextFile, iTextOutput );
    }

    /** {@inheritDoc} */
    public void renderIndividual( Map filesToProcess, File outputDirectory )
        throws DocumentRendererException, IOException
    {
        for ( Iterator it = filesToProcess.keySet().iterator(); it.hasNext(); )
        {
            String key = (String) it.next();
            SiteModule module = (SiteModule) filesToProcess.get( key );
            File fullDoc = new File( getBaseDir(), module.getSourceDirectory() + File.separator + key );

            String output = key;
            String lowerCaseExtension = module.getExtension().toLowerCase( Locale.ENGLISH );
            if ( output.toLowerCase( Locale.ENGLISH ).indexOf( "." + lowerCaseExtension ) != -1 )
            {
                output =
                    output.substring( 0, output.toLowerCase( Locale.ENGLISH ).indexOf( "." + lowerCaseExtension ) );
            }

            File outputITextFile = new File( outputDirectory, output + ".xml" );
            if ( !outputITextFile.getParentFile().exists() )
            {
                outputITextFile.getParentFile().mkdirs();
            }

            File pdfOutputFile = new File( outputDirectory, output + ".pdf" );
            if ( !pdfOutputFile.getParentFile().exists() )
            {
                pdfOutputFile.getParentFile().mkdirs();
            }

            parse( fullDoc, module, outputITextFile );

            generatePdf( outputITextFile, pdfOutputFile );
        }
    }

      //--------------------------------------------
     //
    //--------------------------------------------


    /**
     * Parse a source document and emit results into a sink.
     *
     * @param fullDocPath file to the source document.
     * @param module the site module associated with the source document (determines the parser to use).
     * @param iTextFile the resulting iText xml file.
     * @throws DocumentRendererException in case of a parsing problem.
     * @throws IOException if the source and/or target document cannot be opened.
     */
    private void parse( File fullDoc, SiteModule module, File iTextFile )
        throws DocumentRendererException, IOException
    {
        if ( getLogger().isDebugEnabled() )
        {
            getLogger().debug( "Parsing file " + fullDoc.getAbsolutePath() );
        }

        System.setProperty( "itext.basedir", iTextFile.getParentFile().getAbsolutePath() );

        Writer writer = null;
        ITextSink sink = null;
        try
        {
            writer = WriterFactory.newXmlWriter( iTextFile );
            sink = (ITextSink) new ITextSinkFactory().createSink( writer );

            sink.setClassLoader( new URLClassLoader( new URL[] { iTextFile.getParentFile().toURI().toURL() } ) );

            parse( fullDoc.getAbsolutePath(), module.getParserId(), sink );
        }
        finally
        {
            if ( sink != null )
            {
                sink.flush();
                sink.close();
            }
            IOUtil.close( writer );
            System.getProperties().remove( "itext.basedir" );
        }
    }

    /**
     * Merge all iTextFiles to a single one.
     *
     * @param iTextFiles list of iText xml files.
     * @return Document.
     * @throws DocumentRendererException if any.
     * @throws IOException if any.
     */
    private Document generateDocument( List iTextFiles )
        throws DocumentRendererException, IOException
    {
        Document document = DOCUMENT_BUILDER.newDocument();
        document.appendChild( document.createElement( ElementTags.ITEXT ) ); // Used only to set a root

        for ( int i = 0; i < iTextFiles.size(); i++ )
        {
            File iTextFile = (File) iTextFiles.get( i );

            Document iTextDocument;

            try
            {
                iTextDocument = DOCUMENT_BUILDER.parse( iTextFile );
            }
            catch ( SAXException e )
            {
                throw new DocumentRendererException( "SAX Error : " + e.getMessage() );
            }

            // Only one chapter per doc
            Node chapter = iTextDocument.getElementsByTagName( ElementTags.CHAPTER ).item( 0 );

            try
            {
                document.getDocumentElement().appendChild( document.importNode( chapter, true ) );
            }
            catch ( DOMException e )
            {
                throw new DocumentRendererException( "Error appending chapter for "
                        + iTextFile + " : " + e.getMessage() );
            }
        }

        return document;
    }

    /**
     * Initialize the transformer object.
     *
     * @return an instance of a transformer object.
     * @throws DocumentRendererException if any.
     */
    private Transformer initTransformer()
        throws DocumentRendererException
    {
        try
        {
            Transformer transformer = TRANSFORMER_FACTORY.newTransformer( new StreamSource( ITextPdfRenderer.class
                .getResourceAsStream( XSLT_RESOURCE ) ) );

            transformer.setErrorListener( TRANSFORMER_FACTORY.getErrorListener() );

            transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "false" );

            transformer.setOutputProperty( OutputKeys.INDENT, "yes" );

            transformer.setOutputProperty( OutputKeys.METHOD, "xml" );

            transformer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );

            // No doctype since itext doctype is not up to date!

            return transformer;
        }
        catch ( TransformerConfigurationException e )
        {
            throw new DocumentRendererException( "Error configuring Transformer for " + XSLT_RESOURCE + ": "
                + e.getMessage() );
        }
        catch ( IllegalArgumentException e )
        {
            throw new DocumentRendererException( "Error configuring Transformer for " + XSLT_RESOURCE + ": "
                + e.getMessage() );
        }
    }

    /**
     * Add transformer parameters from a DocumentModel.
     *
     * @param transformer the Transformer to set the parameters.
     * @param documentModel the DocumentModel to take the parameters from, could be null.
     * @param iTextFile the iTextFile not null for the relative paths.
     */
    private void addTransformerParameters( Transformer transformer, DocumentModel documentModel, File iTextFile )
    {
        if ( documentModel == null )
        {
            return;
        }

        // Meta parameters
        boolean hasNullMeta = false;
        if ( documentModel.getMeta() == null )
        {
            hasNullMeta = true;
            documentModel.setMeta( new DocumentMeta() );
        }
        addTransformerParameter( transformer, "meta.author", documentModel.getMeta().getAllAuthorNames(),
                                 System.getProperty( "user.name", "null" ) );
        addTransformerParameter( transformer, "meta.creator", documentModel.getMeta().getCreator(),
                                 System.getProperty( "user.name", "null" ) );
        // see com.lowagie.text.Document#addCreationDate()
        SimpleDateFormat sdf = new SimpleDateFormat( "EEE MMM dd HH:mm:ss zzz yyyy" );
        addTransformerParameter( transformer, "meta.creationdate", documentModel.getMeta().getCreationdate(),
                                 sdf.format( new Date() ) );
        addTransformerParameter( transformer, "meta.keywords", documentModel.getMeta().getAllKeyWords() );
        addTransformerParameter( transformer, "meta.pagesize", documentModel.getMeta().getPageSize(),
                                 ITextUtil.getPageSize( ITextUtil.getDefaultPageSize() ) );
        addTransformerParameter( transformer, "meta.producer", documentModel.getMeta().getGenerator(),
                                 "Apache Doxia iText" );
        addTransformerParameter( transformer, "meta.subject", documentModel.getMeta().getSubject(),
                                 ( documentModel.getMeta().getTitle() != null ? documentModel.getMeta().getTitle()
                                                 : "" ) );
        addTransformerParameter( transformer, "meta.title", documentModel.getMeta().getTitle() );
        if ( hasNullMeta )
        {
            documentModel.setMeta( null );
        }

        // cover parameter
        boolean hasNullCover = false;
        if ( documentModel.getCover() == null )
        {
            hasNullCover = true;
            documentModel.setCover( new DocumentCover() );
        }
        addTransformerParameter( transformer, "cover.author", documentModel.getCover().getAllAuthorNames(),
                                 System.getProperty( "user.name", "null" ) );
        String companyLogo = getLogoURL( documentModel.getCover().getCompanyLogo(), iTextFile.getParentFile() );
        addTransformerParameter( transformer, "cover.companyLogo", companyLogo );
        addTransformerParameter( transformer, "cover.companyName", documentModel.getCover().getCompanyName() );
        if ( documentModel.getCover().getCoverdate() == null )
        {
            documentModel.getCover().setCoverDate( new Date() );
            addTransformerParameter( transformer, "cover.date", documentModel.getCover().getCoverdate() );
            documentModel.getCover().setCoverDate( null );
        }
        else
        {
            addTransformerParameter( transformer, "cover.date", documentModel.getCover().getCoverdate() );
        }
        addTransformerParameter( transformer, "cover.subtitle", documentModel.getCover().getCoverSubTitle() );
        addTransformerParameter( transformer, "cover.title", documentModel.getCover().getCoverTitle() );
        addTransformerParameter( transformer, "cover.type", documentModel.getCover().getCoverType() );
        addTransformerParameter( transformer, "cover.version", documentModel.getCover().getCoverVersion() );
        String projectLogo = getLogoURL( documentModel.getCover().getProjectLogo(), iTextFile.getParentFile() );
        addTransformerParameter( transformer, "cover.projectLogo", projectLogo );
        addTransformerParameter( transformer, "cover.projectName", documentModel.getCover().getProjectName() );
        if ( hasNullCover )
        {
            documentModel.setCover( null );
        }
    }

    /**
     * @param transformer not null
     * @param name not null
     * @param value could be empty
     * @param defaultValue could be empty
     * @since 1.1.1
     */
    private void addTransformerParameter( Transformer transformer, String name, String value, String defaultValue )
    {
        if ( StringUtils.isEmpty( value ) )
        {
            addTransformerParameter( transformer, name, defaultValue );
        }
        else
        {
            addTransformerParameter( transformer, name, value );
        }
    }

    /**
     * @param transformer not null
     * @param name not null
     * @param value could be empty
     * @since 1.1.1
     */
    private void addTransformerParameter( Transformer transformer, String name, String value )
    {
        if ( StringUtils.isEmpty( value ) )
        {
            return;
        }

        transformer.setParameter( name, value );
    }

    /**
     * Transform a document to an iTextFile.
     *
     * @param documentModel the DocumentModel to take the parameters from, could be null.
     * @param document the Document to transform.
     * @param iTextFile the resulting iText xml file.
     * @throws DocumentRendererException in case of a transformation error.
     */
    private void transform( DocumentModel documentModel, Document document, File iTextFile )
        throws DocumentRendererException
    {
        Transformer transformer = initTransformer();

        addTransformerParameters( transformer, documentModel, iTextFile );

        try
        {
            transformer.transform( new DOMSource( document ), new StreamResult( iTextFile ) );
        }
        catch ( TransformerException e )
        {
            throw new DocumentRendererException( "Error transforming Document " + document + ": " + e.getMessage() );
        }
    }

    /**
     * @param filesToProcess not null
     * @param outputDirectory not null
     * @return a list of all parsed files.
     * @throws DocumentRendererException if any
     * @throws IOException if any
     * @since 1.1.1
     */
    private List parseAllFiles( Map filesToProcess, File outputDirectory )
        throws DocumentRendererException, IOException
    {
        List iTextFiles = new LinkedList();
        for ( Iterator it = filesToProcess.keySet().iterator(); it.hasNext(); )
        {
            String key = (String) it.next();
            SiteModule module = (SiteModule) filesToProcess.get( key );
            File fullDoc = new File( getBaseDir(), module.getSourceDirectory() + File.separator + key );

            String outputITextName = key.substring( 0, key.lastIndexOf( "." ) + 1 ) + "xml";
            File outputITextFileTmp = new File( outputDirectory, outputITextName );
            outputITextFileTmp.deleteOnExit();
            if ( !outputITextFileTmp.getParentFile().exists() )
            {
                outputITextFileTmp.getParentFile().mkdirs();
            }

            iTextFiles.add( outputITextFileTmp );
            parse( fullDoc, module, outputITextFileTmp );
        }

        return iTextFiles;
    }

    /**
     * @param filesToProcess not null
     * @param outputDirectory not null
     * @return a list of all parsed files.
     * @throws DocumentRendererException if any
     * @throws IOException if any
     * @since 1.1.1
     */
    private List parseTOCFiles( Map filesToProcess, File outputDirectory, DocumentModel documentModel )
        throws DocumentRendererException, IOException
    {
        List iTextFiles = new LinkedList();
        for ( Iterator it = documentModel.getToc().getItems().iterator(); it.hasNext(); )
        {
            DocumentTOCItem tocItem = (DocumentTOCItem) it.next();

            if ( tocItem.getRef() == null )
            {
                getLogger().debug(
                                   "No ref defined for the tocItem '" + tocItem.getName()
                                       + "' in the document descriptor. IGNORING" );
                continue;
            }

            String href = StringUtils.replace( tocItem.getRef(), "\\", "/" );
            if ( href.lastIndexOf( "." ) != -1 )
            {
                href = href.substring( 0, href.lastIndexOf( "." ) );
            }

            for ( Iterator i = siteModuleManager.getSiteModules().iterator(); i.hasNext(); )
            {
                SiteModule module = (SiteModule) i.next();
                File moduleBasedir = new File( getBaseDir(), module.getSourceDirectory() );

                if ( moduleBasedir.exists() )
                {
                    String doc = href + "." + module.getExtension();
                    File source = new File( moduleBasedir, doc );

                    if ( source.exists() )
                    {
                        String outputITextName = doc.substring( 0, doc.lastIndexOf( "." ) + 1 ) + "xml";
                        File outputITextFileTmp = new File( outputDirectory, outputITextName );
                        outputITextFileTmp.deleteOnExit();
                        if ( !outputITextFileTmp.getParentFile().exists() )
                        {
                            outputITextFileTmp.getParentFile().mkdirs();
                        }

                        iTextFiles.add( outputITextFileTmp );
                        parse( source, module, outputITextFileTmp );
                    }
                }
            }
        }

        return iTextFiles;
    }

    /**
     * @param logo
     * @param parentFile
     * @return the logo url or null if unable to create it.
     * @since 1.1.1
     */
    private String getLogoURL( String logo, File parentFile )
    {
        if ( logo == null )
        {
            return null;
        }

        try
        {
            return new URL( logo ).toString();
        }
        catch ( MalformedURLException e )
        {
            try
            {
                File f = new File( parentFile, logo );
                if ( !f.exists() )
                {
                    getLogger().warn( "The logo " + f.getAbsolutePath() + " doesnt exist. IGNORING" );
                }
                else
                {
                    return f.toURL().toString();
                }
            }
            catch ( MalformedURLException e1 )
            {
                // nope
            }
        }

        return null;
    }
}
