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

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.xml.sax.SAXException;

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

import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
import org.apache.xmlgraphics.image.loader.util.Penalty;
import org.apache.xmlgraphics.io.ResourceResolver;

import org.apache.fop.accessibility.Accessibility;
import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.configuration.Configuration;
import org.apache.fop.configuration.ConfigurationException;
import org.apache.fop.configuration.DefaultConfigurationBuilder;
import org.apache.fop.fonts.FontManagerConfigurator;
import org.apache.fop.hyphenation.HyphenationTreeCache;
import org.apache.fop.hyphenation.Hyphenator;
import org.apache.fop.util.LogUtil;

/**
 * Parses the FOP configuration file and returns a {@link FopFactoryBuilder} which builds a
 * {@link FopFactory}.
 */
public class FopConfParser {

    private static final String PREFER_RENDERER = "prefer-renderer";
    private static final String TABLE_BORDER_OVERPAINT = "table-border-overpaint";

    private final Log log = LogFactory.getLog(FopConfParser.class);

    private final FopFactoryBuilder fopFactoryBuilder;

    /**
     * Constructor that takes the FOP conf in the form of an {@link InputStream}. A default base URI
     * must be given as a fall-back mechanism for URI resolution.
     *
     * @param fopConfStream the fop conf input stream
     * @param enviro the profile of the FOP deployment environment
     * @throws SAXException if a SAX error was thrown parsing the FOP conf
     * @throws IOException if an I/O error is thrown while parsing the FOP conf
     */
    public FopConfParser(InputStream fopConfStream, EnvironmentProfile enviro)
            throws SAXException, IOException {
        this(fopConfStream, enviro.getDefaultBaseURI(), enviro);
    }

    /**
     * Constructor that takes the FOP conf in the form of an {@link InputStream}. A default base URI
     * must be given as a fall-back mechanism for URI resolution.
     *
     * @param fopConfStream the fop conf input stream
     * @param defaultBaseURI the default base URI
     * @param resourceResolver the URI resolver
     * @throws SAXException if a SAX error was thrown parsing the FOP conf
     * @throws IOException if an I/O error is thrown while parsing the FOP conf
     */
    public FopConfParser(InputStream fopConfStream, URI defaultBaseURI,
            ResourceResolver resourceResolver) throws SAXException, IOException {
        this(fopConfStream, defaultBaseURI,
                EnvironmentalProfileFactory.createDefault(defaultBaseURI, resourceResolver));
    }

    /**
     * Constructor that takes the FOP conf in the form of an {@link InputStream}. A default base URI
     * must be given as a fall-back mechanism for URI resolution. The default URI resolvers is used.
     *
     * @param fopConfStream the fop conf input stream
     * @param defaultBaseURI the default base URI
     * @throws SAXException if a SAX error was thrown parsing the FOP conf
     * @throws IOException if an I/O error is thrown while parsing the FOP conf
     */
    public FopConfParser(InputStream fopConfStream, URI defaultBaseURI) throws SAXException,
            IOException {
        this(fopConfStream, defaultBaseURI, ResourceResolverFactory.createDefaultResourceResolver());
    }

    /**
     * Constructor that takes the FOP conf and uses the default URI resolver.
     *
     * @param fopConfFile the FOP conf file
     * @throws SAXException if a SAX error was thrown parsing the FOP conf
     * @throws IOException if an I/O error is thrown while parsing the FOP conf
     */
    public FopConfParser(File fopConfFile) throws SAXException, IOException {
        this(fopConfFile, ResourceResolverFactory.createDefaultResourceResolver());
    }

    /**
     * Constructor that takes the FOP conf and a default base URI and uses the default URI resolver.
     *
     * @param fopConfFile the FOP conf file
     * @param defaultBaseURI the default base URI
     * @throws SAXException if a SAX error was thrown parsing the FOP conf
     * @throws IOException if an I/O error is thrown while parsing the FOP conf
     */
    public FopConfParser(File fopConfFile, URI defaultBaseURI) throws SAXException, IOException {
        this(new FileInputStream(fopConfFile), fopConfFile.toURI(),
                EnvironmentalProfileFactory.createDefault(defaultBaseURI,
                        ResourceResolverFactory.createDefaultResourceResolver()));
    }

    /**
     * Constructor that parses the FOP conf and uses the URI resolver given.
     *
     * @param fopConfFile the FOP conf file
     * @param resourceResolver the URI resolver
     * @throws SAXException if a SAX error was thrown parsing the FOP conf
     * @throws IOException if an I/O error is thrown while parsing the FOP conf
     */
    public FopConfParser(File fopConfFile, ResourceResolver resourceResolver)
            throws SAXException, IOException {
        this(new FileInputStream(fopConfFile), fopConfFile.getParentFile().toURI(), resourceResolver);
    }

    public FopConfParser(InputStream fopConfStream, URI baseURI, EnvironmentProfile enviro)
            throws SAXException, IOException {
        DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
        Configuration cfg;
        try {
            cfg = cfgBuilder.build(fopConfStream);
        } catch (ConfigurationException e) {
            throw new FOPException(e);
        }
        // The default base URI is taken from the directory in which the fopConf resides
        fopFactoryBuilder = new FopFactoryBuilder(enviro).setConfiguration(cfg);
        configure(baseURI, enviro.getResourceResolver(), cfg);
    }

    private void configure(final URI baseURI, final ResourceResolver resourceResolver,
            Configuration cfg) throws FOPException {
        if (log.isDebugEnabled()) {
            log.debug("Initializing FopFactory Configuration");
        }

        // strict fo validation
        if (cfg.getChild("strict-validation", false) != null) {
            try {
                boolean strict = cfg.getChild("strict-validation").getValueAsBoolean();
                fopFactoryBuilder.setStrictFOValidation(strict);
            } catch (ConfigurationException e) {
                LogUtil.handleException(log, e, false);
            }
        }

        boolean strict = false;
        if (cfg.getChild("strict-configuration", false) != null) {
            try {
                strict = cfg.getChild("strict-configuration").getValueAsBoolean();
                fopFactoryBuilder.setStrictUserConfigValidation(strict);
            } catch (ConfigurationException e) {
                LogUtil.handleException(log, e, false);
            }
        }

        if (cfg.getChild("accessibility", false) != null) {
            try {
                fopFactoryBuilder.setAccessibility(cfg.getChild("accessibility").getValueAsBoolean());
                fopFactoryBuilder.setKeepEmptyTags(
                        cfg.getChild("accessibility").getAttributeAsBoolean(Accessibility.KEEP_EMPTY_TAGS, true));
            } catch (ConfigurationException e) {
                LogUtil.handleException(log, e, false);
            }
        }

        // base definitions for relative path resolution
        if (cfg.getChild("base", false) != null) {
            try {
                URI confUri = InternalResourceResolver.getBaseURI(cfg.getChild("base").getValue(null));
                fopFactoryBuilder.setBaseURI(baseURI.resolve(confUri));
            } catch (URISyntaxException use) {
                LogUtil.handleException(log, use, strict);
            }
        }

        // renderer options
        if (cfg.getChild("source-resolution", false) != null) {
            float srcRes = cfg.getChild("source-resolution").getValueAsFloat(
                    FopFactoryConfig.DEFAULT_SOURCE_RESOLUTION);
            fopFactoryBuilder.setSourceResolution(srcRes);
            if (log.isDebugEnabled()) {
                log.debug("source-resolution set to: " + srcRes + "dpi");
            }
        }
        if (cfg.getChild("target-resolution", false) != null) {
            float targetRes = cfg.getChild("target-resolution").getValueAsFloat(
                    FopFactoryConfig.DEFAULT_TARGET_RESOLUTION);
            fopFactoryBuilder.setTargetResolution(targetRes);
            if (log.isDebugEnabled()) {
                log.debug("target-resolution set to: " + targetRes + "dpi");
            }
        }
        if (cfg.getChild("break-indent-inheritance", false) != null) {
            try {
                fopFactoryBuilder.setBreakIndentInheritanceOnReferenceAreaBoundary(
                             cfg.getChild("break-indent-inheritance").getValueAsBoolean());
            } catch (ConfigurationException e) {
                LogUtil.handleException(log, e, strict);
            }
        }
        Configuration pageConfig = cfg.getChild("default-page-settings");
        if (pageConfig.getAttribute("height", null) != null) {
            String pageHeight = pageConfig.getAttribute("height",
                    FopFactoryConfig.DEFAULT_PAGE_HEIGHT);
            fopFactoryBuilder.setPageHeight(pageHeight);
            if (log.isInfoEnabled()) {
                log.info("Default page-height set to: " + pageHeight);
            }
        }
        if (pageConfig.getAttribute("width", null) != null) {
            String pageWidth = pageConfig.getAttribute("width",
                    FopFactoryConfig.DEFAULT_PAGE_WIDTH);
            fopFactoryBuilder.setPageWidth(pageWidth);
            if (log.isInfoEnabled()) {
                log.info("Default page-width set to: " + pageWidth);
            }
        }

        if (cfg.getChild("complex-scripts") != null) {
            Configuration csConfig = cfg.getChild("complex-scripts");
            fopFactoryBuilder.setComplexScriptFeatures(!csConfig.getAttributeAsBoolean("disabled",
                    false));
        }

        setHyphenationBase(cfg, resourceResolver, baseURI, fopFactoryBuilder);
        setHyphPatNames(cfg, fopFactoryBuilder, strict);

        // prefer Renderer over IFDocumentHandler
        if (cfg.getChild(PREFER_RENDERER, false) != null) {
            try {
                fopFactoryBuilder.setPreferRenderer(
                             cfg.getChild(PREFER_RENDERER).getValueAsBoolean());
            } catch (ConfigurationException e) {
                LogUtil.handleException(log, e, strict);
            }
        }

        if (cfg.getChild(TABLE_BORDER_OVERPAINT, false) != null) {
            try {
                fopFactoryBuilder.setTableBorderOverpaint(
                        cfg.getChild(TABLE_BORDER_OVERPAINT).getValueAsBoolean());
            } catch (ConfigurationException e) {
                LogUtil.handleException(log, e, false);
            }
        }

        // configure font manager
        new FontManagerConfigurator(cfg, baseURI, fopFactoryBuilder.getBaseURI(), resourceResolver)
                .configure(fopFactoryBuilder.getFontManager(), strict);

        // configure image loader framework
        configureImageLoading(cfg.getChild("image-loading", false), strict);
    }


    private void setHyphenationBase(Configuration cfg, ResourceResolver resourceResolver, URI baseURI,
                                    FopFactoryBuilder fopFactoryBuilder) throws FOPException {
        if (cfg.getChild("hyphenation-base", false) != null) {
            try {
                URI fontBase = InternalResourceResolver.getBaseURI(cfg.getChild("hyphenation-base").getValue(null));
                fopFactoryBuilder.setHyphenBaseResourceResolver(
                        ResourceResolverFactory.createInternalResourceResolver(
                                baseURI.resolve(fontBase), resourceResolver));
            } catch (URISyntaxException use) {
                LogUtil.handleException(log, use, true);
            }
        } else {
            fopFactoryBuilder.setHyphenBaseResourceResolver(
                    ResourceResolverFactory.createInternalResourceResolver(
                            fopFactoryBuilder.getBaseURI(), resourceResolver));
        }
    }

    private void setHyphPatNames(Configuration cfg, FopFactoryBuilder builder, boolean strict)
            throws FOPException {
        Configuration[] hyphPatConfig = cfg.getChildren("hyphenation-pattern");
        if (hyphPatConfig.length != 0) {
            Map<String, String> hyphPatNames = new HashMap<String, String>();
            for (Configuration aHyphPatConfig : hyphPatConfig) {
                String lang;
                String country;
                String filename;
                StringBuffer error = new StringBuffer();
                String location = aHyphPatConfig.getLocation();

                lang = aHyphPatConfig.getAttribute("lang", null);
                if (lang == null) {
                    addError("The lang attribute of a hyphenation-pattern configuration"
                            + " element must exist (" + location + ")", error);
                } else if (!lang.matches("[a-zA-Z]{2}")) {
                    addError("The lang attribute of a hyphenation-pattern configuration"
                            + " element must consist of exactly two letters ("
                            + location + ")", error);
                }
                lang = lang.toLowerCase(Locale.getDefault());

                country = aHyphPatConfig.getAttribute("country", null);
                if ("".equals(country)) {
                    country = null;
                }
                if (country != null) {
                    if (!country.matches("[a-zA-Z]{2}")) {
                        addError("The country attribute of a hyphenation-pattern configuration"
                                + " element must consist of exactly two letters ("
                                + location + ")", error);
                    }
                    country = country.toUpperCase(Locale.getDefault());
                }

                filename = aHyphPatConfig.getValue(null);
                if (filename == null) {
                    addError("The value of a hyphenation-pattern configuration"
                            + " element may not be empty (" + location + ")", error);
                }

                if (error.length() != 0) {
                    LogUtil.handleError(log, error.toString(), strict);
                    continue;
                }

                String llccKey = HyphenationTreeCache.constructLlccKey(lang, country);

                String extension = aHyphPatConfig.getAttribute("extension", null);
                if ("xml".equals(extension)) {
                    hyphPatNames.put(llccKey, filename + Hyphenator.XMLTYPE);
                } else if ("hyp".equals(extension)) {
                    hyphPatNames.put(llccKey, filename + Hyphenator.HYPTYPE);
                } else {
                    hyphPatNames.put(llccKey, filename);
                }
                if (log.isDebugEnabled()) {
                    log.debug("Using hyphenation pattern filename " + filename
                            + " for lang=\"" + lang + "\""
                            + (country != null ? ", country=\"" + country + "\"" : ""));
                }
            }
            builder.setHyphPatNames(hyphPatNames);
        }
    }

    private static void addError(String message, StringBuffer error) {
        if (error.length() != 0) {
            error.append(". ");
        }
        error.append(message);
    }

    private void configureImageLoading(Configuration parent, boolean strict) throws FOPException {
        if (parent == null) {
            return;
        }
        ImageImplRegistry registry = fopFactoryBuilder.getImageManager().getRegistry();
        Configuration[] penalties = parent.getChildren("penalty");
        try {
            for (Configuration penaltyCfg : penalties) {
                String className = penaltyCfg.getAttribute("class");
                String value = penaltyCfg.getAttribute("value");
                Penalty p = null;
                if (value.toUpperCase(Locale.getDefault()).startsWith("INF")) {
                    p = Penalty.INFINITE_PENALTY;
                } else {
                    try {
                        p = Penalty.toPenalty(Integer.parseInt(value));
                    } catch (NumberFormatException nfe) {
                        LogUtil.handleException(log, nfe, strict);
                    }
                }
                if (p != null) {
                    registry.setAdditionalPenalty(className, p);
                }
            }
        } catch (ConfigurationException e) {
            LogUtil.handleException(log, e, strict);
        }
    }

    /**
     * Returns the {@link FopFactoryBuilder}.
     *
     * @return the object for configuring the {@link FopFactory}
     */
    public FopFactoryBuilder getFopFactoryBuilder() {
        return fopFactoryBuilder;
    }
}
