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

/* $Id$ */

package org.apache.fop.cli;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.render.awt.viewer.Renderable;

/**
 * Class for handling files input from command line
 * either with XML and XSLT files (and optionally xsl
 * parameters) or FO File input alone.
 */
public class InputHandler implements ErrorListener, Renderable {

    /** original source file */
    protected File sourcefile;
    private File stylesheet;  // for XML/XSLT usage
    private Vector xsltParams; // for XML/XSLT usage
    private EntityResolver entityResolver;
    private URIResolver uriResolver;

    /** the logger */
    protected Log log = LogFactory.getLog(InputHandler.class);

    /**
     * Constructor for XML->XSLT->FO input
     *
     * @param xmlfile XML file
     * @param xsltfile XSLT file
     * @param params Vector of command-line parameters (name, value,
     *      name, value, ...) for XSL stylesheet, null if none
     */
    public InputHandler(File xmlfile, File xsltfile, Vector params) {
        sourcefile  = xmlfile;
        stylesheet = xsltfile;
        xsltParams = params;
    }

    /**
     * Constructor for XML->XSLT->FO input
     *
     * @param xmlfile XML file
     * @param xsltfile XSLT file
     * @param params Vector of command-line parameters (name, value,
     *      name, value, ...) for XSL stylesheet, null if none
     * @param useCatalogResolver if true, use a catalog resolver
     *      for XML parsing and XSLT URI resolution
     */
    public InputHandler(File xmlfile, File xsltfile, Vector params, boolean useCatalogResolver) {
        this(xmlfile, xsltfile, params);
        if (useCatalogResolver) {
            createCatalogResolver();
        }
    }

    /**
     * Constructor for FO input
     * @param fofile the file to read the FO document.
     */
    public InputHandler(File fofile) {
        sourcefile = fofile;
    }

    /**
     * Generate a document, given an initialized Fop object
     * @param userAgent the user agent
     * @param outputFormat the output format to generate (MIME type, see MimeConstants)
     * @param out the output stream to write the generated output to (may be null if not applicable)
     * @throws FOPException in case of an error during processing
     */
    public void renderTo(FOUserAgent userAgent, String outputFormat, OutputStream out)
                throws FOPException {

        FopFactory factory = userAgent.getFactory();
        Fop fop;
        if (out != null) {
            fop = factory.newFop(outputFormat, userAgent, out);
        } else {
            fop = factory.newFop(outputFormat, userAgent);
        }

        // if base URL was not explicitly set in FOUserAgent, obtain here
        if (fop.getUserAgent().getBaseURL() == null && sourcefile != null) {
            String baseURL = null;

            try {
                baseURL = new File(sourcefile.getAbsolutePath()).
                        getParentFile().toURI().toURL().toExternalForm();
            } catch (Exception e) {
                baseURL = "";
            }
            fop.getUserAgent().setBaseURL(baseURL);
        }

        // Resulting SAX events (the generated FO) must be piped through to FOP
        Result res = new SAXResult(fop.getDefaultHandler());

        transformTo(res);
    }

    /** {@inheritDoc} */
    public void renderTo(FOUserAgent userAgent, String outputFormat) throws FOPException {
        renderTo(userAgent, outputFormat, null);
    }

    /**
     * In contrast to render(Fop) this method only performs the XSLT stage and saves the
     * intermediate XSL-FO file to the output file.
     * @param out OutputStream to write the transformation result to.
     * @throws FOPException in case of an error during processing
     */
    public void transformTo(OutputStream out) throws FOPException {
        Result res = new StreamResult(out);
        transformTo(res);
    }

    /**
     * Creates a Source for the main input file. Processes XInclude if
     * available in the XML parser.
     *
     * @return the Source for the main input file
     */
    protected Source createMainSource() {
        Source source;
        InputStream in;
        String uri;
        if (this.sourcefile != null) {
            try {
                in = new java.io.FileInputStream(this.sourcefile);
                uri = this.sourcefile.toURI().toASCIIString();
            } catch (FileNotFoundException e) {
                //handled elsewhere
                return new StreamSource(this.sourcefile);
            }
        } else {
            in = System.in;
            uri = null;
        }
        try {
            InputSource is = new InputSource(in);
            is.setSystemId(uri);
            XMLReader xr = getXMLReader();
            if (entityResolver != null) {
                xr.setEntityResolver(entityResolver);
            }
            source = new SAXSource(xr, is);
        } catch (SAXException e) {
            if (this.sourcefile != null) {
                source = new StreamSource(this.sourcefile);
            } else {
                source = new StreamSource(in, uri);
            }
        } catch (ParserConfigurationException e) {
            if (this.sourcefile != null) {
                source = new StreamSource(this.sourcefile);
            } else {
                source = new StreamSource(in, uri);
            }
        }
        return source;
    }

    /**
     * Creates a catalog resolver and uses it for XML parsing and XSLT URI resolution.
     * Tries the Apache Commons Resolver, and if unsuccessful,
     * tries the same built into Java 6.
     */
    private void createCatalogResolver() {
        String[] classNames = new String[] {
                "org.apache.xml.resolver.tools.CatalogResolver",
                "com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver"};
        Class resolverClass = null;
        for (int i = 0; i < classNames.length && resolverClass == null; ++i) {
            try {
                resolverClass = Class.forName(classNames[i]);
            } catch (ClassNotFoundException e) {
                // No worries
            }
        }
        if (resolverClass == null) {
            log.error("Could not find catalog resolver in class path");
            return;
        }
        try {
            entityResolver = (EntityResolver) resolverClass.newInstance();
            uriResolver = (URIResolver) resolverClass.newInstance();
        } catch (InstantiationException e) {
            log.error("Error creating the catalog resolver: " + e.getMessage());
        } catch (IllegalAccessException e) {
            log.error("Error creating the catalog resolver: " + e.getMessage());
        }
    }

    /**
     * Creates a Source for the selected stylesheet.
     *
     * @return the Source for the selected stylesheet or null if there's no stylesheet
     */
    protected Source createXSLTSource() {
        Source xslt = null;
        if (this.stylesheet != null) {
            if (entityResolver != null) {
                try {
                    InputSource is = new InputSource(this.stylesheet.getPath());
                    XMLReader xr = getXMLReader();
                    xr.setEntityResolver(entityResolver);
                    xslt = new SAXSource(xr, is);
                } catch (SAXException e) {
                    // return StreamSource
                } catch (ParserConfigurationException e) {
                    // return StreamSource
                }
            }
            if (xslt == null) {
                xslt = new StreamSource(this.stylesheet);
            }
        }
        return xslt;
    }

    private XMLReader getXMLReader() throws ParserConfigurationException, SAXException {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature("http://xml.org/sax/features/namespaces", true);
        spf.setFeature("http://apache.org/xml/features/xinclude", true);
        XMLReader xr = spf.newSAXParser().getXMLReader();
        return xr;
    }

    /**
     * Transforms the input document to the input format expected by FOP using XSLT.
     * @param result the Result object where the result of the XSL transformation is sent to
     * @throws FOPException in case of an error during processing
     */
    protected void transformTo(Result result) throws FOPException {
        try {
            // Setup XSLT
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer;

            Source xsltSource = createXSLTSource();
            if (xsltSource == null) {   // FO Input
                transformer = factory.newTransformer();
            } else {    // XML/XSLT input
                transformer = factory.newTransformer(xsltSource);

                // Set the value of parameters, if any, defined for stylesheet
                if (xsltParams != null) {
                    for (int i = 0; i < xsltParams.size(); i += 2) {
                        transformer.setParameter((String) xsltParams.elementAt(i),
                            (String) xsltParams.elementAt(i + 1));
                    }
                }
                if (uriResolver != null) {
                    transformer.setURIResolver(uriResolver);
                }
            }
            transformer.setErrorListener(this);

            // Create a SAXSource from the input Source file
            Source src = createMainSource();

            // Start XSLT transformation and FOP processing
            transformer.transform(src, result);

        } catch (Exception e) {
            throw new FOPException(e);
        }
    }

    // --- Implementation of the ErrorListener interface ---

    /**
     * {@inheritDoc}
     */
    public void warning(TransformerException exc) {
        log.warn(exc.getLocalizedMessage());
    }

    /**
     * {@inheritDoc}
     */
    public void error(TransformerException exc) {
        log.error(exc.toString());
    }

    /**
     * {@inheritDoc}
     */
    public void fatalError(TransformerException exc)
            throws TransformerException {
        throw exc;
    }

}
