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

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.Map;
import java.util.Set;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXTransformerFactory;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;

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

import org.apache.xmlgraphics.util.QName;

import org.apache.fop.accessibility.AccessibilityEventProducer;
import org.apache.fop.accessibility.StructureTreeBuilder;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.render.intermediate.extensions.DocumentNavigationExtensionConstants;
import org.apache.fop.render.intermediate.extensions.DocumentNavigationHandler;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.DOMBuilderContentHandlerFactory;
import org.apache.fop.util.DefaultErrorListener;
import org.apache.fop.util.DelegatingContentHandler;
import org.apache.fop.util.XMLUtil;

/**
 * This is a parser for the intermediate format XML which converts the intermediate file into
 * {@link IFPainter} events.
 */
public class IFParser implements IFConstants {

    /** Logger instance */
    protected static Log log = LogFactory.getLog(IFParser.class);

    private static SAXTransformerFactory tFactory
        = (SAXTransformerFactory)SAXTransformerFactory.newInstance();

    private static Set handledNamespaces = new java.util.HashSet();

    static {
        handledNamespaces.add(XMLNS_NAMESPACE_URI);
        handledNamespaces.add(XML_NAMESPACE);
        handledNamespaces.add(NAMESPACE);
        handledNamespaces.add(XLINK_NAMESPACE);
    }

    /**
     * Parses an intermediate file and paints it.
     * @param src the Source instance pointing to the intermediate file
     * @param documentHandler the intermediate format document handler used to process the IF events
     * @param userAgent the user agent
     * @throws TransformerException if an error occurs while parsing the area tree XML
     * @throws IFException if an IF-related error occurs inside the target document handler
     */
    public void parse(Source src, IFDocumentHandler documentHandler, FOUserAgent userAgent)
            throws TransformerException, IFException {
        try {
            Transformer transformer = tFactory.newTransformer();
            transformer.setErrorListener(new DefaultErrorListener(log));

            SAXResult res = new SAXResult(getContentHandler(documentHandler, userAgent));

            transformer.transform(src, res);
        } catch (TransformerException te) {
            //Unpack original IFException if applicable
            if (te.getCause() instanceof SAXException) {
                SAXException se = (SAXException)te.getCause();
                if (se.getCause() instanceof IFException) {
                    throw (IFException)se.getCause();
                }
            } else if (te.getCause() instanceof IFException) {
                throw (IFException)te.getCause();
            }
            throw te;
        }
    }

    /**
     * Creates a new ContentHandler instance that you can send the area tree XML to. The parsed
     * pages are added to the AreaTreeModel instance you pass in as a parameter.
     * @param documentHandler the intermediate format document handler used to process the IF events
     * @param userAgent the user agent
     * @return the ContentHandler instance to receive the SAX stream from the area tree XML
     */
    public ContentHandler getContentHandler(IFDocumentHandler documentHandler,
                    FOUserAgent userAgent) {
        ElementMappingRegistry elementMappingRegistry
            = userAgent.getFactory().getElementMappingRegistry();
        return new Handler(documentHandler, userAgent, elementMappingRegistry);
    }

    private static class Handler extends DefaultHandler {

        private Map elementHandlers = new java.util.HashMap();

        private IFDocumentHandler documentHandler;
        private IFPainter painter;
        private FOUserAgent userAgent;
        private ElementMappingRegistry elementMappingRegistry;

        private Attributes lastAttributes;

        private StringBuffer content = new StringBuffer();
        private boolean ignoreCharacters = true;

        //private Stack delegateStack = new Stack();
        private int delegateDepth;
        private ContentHandler delegate;
        private boolean inForeignObject;
        private Document foreignObject;

        private ContentHandler navParser;

        private StructureTreeBuilder structureTreeBuilder;

        private ContentHandler structureTreeBuilderWrapper;

        private Attributes pageSequenceAttributes;

        private final class StructureTreeBuilderWrapper extends DelegatingContentHandler {

            private StructureTreeBuilderWrapper()
                    throws SAXException {
                super(structureTreeBuilder.getHandlerForNextPageSequence());
            }

            public void endDocument() throws SAXException {
                super.endDocument();
                startIFElement(EL_PAGE_SEQUENCE, pageSequenceAttributes);
                pageSequenceAttributes = null;
            }
        }

        public Handler(IFDocumentHandler documentHandler, FOUserAgent userAgent,
                ElementMappingRegistry elementMappingRegistry) {
            this.documentHandler = documentHandler;
            this.userAgent = userAgent;
            this.elementMappingRegistry = elementMappingRegistry;
            elementHandlers.put(EL_DOCUMENT, new DocumentHandler());
            elementHandlers.put(EL_HEADER, new DocumentHeaderHandler());
            elementHandlers.put(EL_TRAILER, new DocumentTrailerHandler());
            elementHandlers.put(EL_PAGE_SEQUENCE, new PageSequenceHandler());
            elementHandlers.put(EL_PAGE, new PageHandler());
            elementHandlers.put(EL_PAGE_HEADER, new PageHeaderHandler());
            elementHandlers.put(EL_PAGE_CONTENT, new PageContentHandler());
            elementHandlers.put(EL_PAGE_TRAILER, new PageTrailerHandler());
            //Page content
            elementHandlers.put(EL_VIEWPORT, new ViewportHandler());
            elementHandlers.put(EL_GROUP, new GroupHandler());
            elementHandlers.put(EL_FONT, new FontHandler());
            elementHandlers.put(EL_TEXT, new TextHandler());
            elementHandlers.put(EL_CLIP_RECT, new ClipRectHandler());
            elementHandlers.put(EL_RECT, new RectHandler());
            elementHandlers.put(EL_LINE, new LineHandler());
            elementHandlers.put(EL_BORDER_RECT, new BorderRectHandler());
            elementHandlers.put(EL_IMAGE, new ImageHandler());

            if (userAgent.isAccessibilityEnabled()) {
                structureTreeBuilder = new StructureTreeBuilder(tFactory);
                userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
            }
        }

        private void establishForeignAttributes(Map foreignAttributes) {
            documentHandler.getContext().setForeignAttributes(foreignAttributes);
        }

        private void resetForeignAttributes() {
            documentHandler.getContext().resetForeignAttributes();
        }

        private void establishStructurePointer(String ptr) {
            documentHandler.getContext().setStructurePointer(ptr);
        }

        private void resetStructurePointer() {
            documentHandler.getContext().resetStructurePointer();
        }

        /** {@inheritDoc} */
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                    throws SAXException {
            if (delegate != null) {
                delegateDepth++;
                delegate.startElement(uri, localName, qName, attributes);
            } else {
                boolean handled = true;
                if (NAMESPACE.equals(uri)) {
                    if (localName.equals(EL_PAGE_SEQUENCE) && userAgent.isAccessibilityEnabled()) {
                        pageSequenceAttributes = new AttributesImpl(attributes);
                        structureTreeBuilderWrapper = new StructureTreeBuilderWrapper();
                    } else if (localName.equals(EL_STRUCTURE_TREE)) {
                        if (userAgent.isAccessibilityEnabled()) {
                            delegate = structureTreeBuilderWrapper;
                        } else {
                            /* Delegate to a handler that does nothing */
                            delegate = new DefaultHandler();
                        }
                        delegateDepth++;
                        delegate.startDocument();
                        delegate.startElement(uri, localName, qName, attributes);
                    } else {
                        if (pageSequenceAttributes != null) {
                            /*
                             * This means that no structure-element tag was
                             * found in the XML, otherwise a
                             * StructureTreeBuilderWrapper object would have
                             * been created, which would have reset the
                             * pageSequenceAttributes field.
                             */
                            AccessibilityEventProducer.Provider
                                    .get(userAgent.getEventBroadcaster())
                                    .noStructureTreeInXML(this);
                        }
                        handled = startIFElement(localName, attributes);
                    }
                } else if (DocumentNavigationExtensionConstants.NAMESPACE.equals(uri)) {
                    if (this.navParser == null) {
                        this.navParser = new DocumentNavigationHandler(
                                this.documentHandler.getDocumentNavigationHandler());
                    }
                    delegate = this.navParser;
                    delegateDepth++;
                    delegate.startDocument();
                    delegate.startElement(uri, localName, qName, attributes);
                } else {
                    ContentHandlerFactoryRegistry registry
                            = userAgent.getFactory().getContentHandlerFactoryRegistry();
                    ContentHandlerFactory factory = registry.getFactory(uri);
                    if (factory == null) {
                        DOMImplementation domImplementation
                            = elementMappingRegistry.getDOMImplementationForNamespace(uri);
                        if (domImplementation == null) {
                            domImplementation = ElementMapping.getDefaultDOMImplementation();
                            /*
                            throw new SAXException("No DOMImplementation could be"
                                    + " identified to handle namespace: " + uri);
                                    */
                        }
                        factory = new DOMBuilderContentHandlerFactory(uri, domImplementation);
                    }
                    delegate = factory.createContentHandler();
                    delegateDepth++;
                    delegate.startDocument();
                    delegate.startElement(uri, localName, qName, attributes);
                }
                if (!handled) {
                    if (uri == null || uri.length() == 0) {
                        throw new SAXException("Unhandled element " + localName
                                + " in namespace: " + uri);
                    } else {
                        log.warn("Unhandled element " + localName
                                + " in namespace: " + uri);
                    }
                }
            }
        }

        private boolean startIFElement(String localName, Attributes attributes)
                throws SAXException {
            lastAttributes = new AttributesImpl(attributes);
            ElementHandler elementHandler = (ElementHandler)elementHandlers.get(localName);
            content.setLength(0);
            ignoreCharacters = true;
            if (elementHandler != null) {
                ignoreCharacters = elementHandler.ignoreCharacters();
                try {
                    elementHandler.startElement(attributes);
                } catch (IFException ife) {
                    handleIFException(ife);
                }
                return true;
            } else {
                return false;
            }
        }

        private void handleIFException(IFException ife) throws SAXException {
            if (ife.getCause() instanceof SAXException) {
                //unwrap
                throw (SAXException)ife.getCause();
            } else {
                //wrap
                throw new SAXException(ife);
            }
        }


        /** {@inheritDoc} */
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (delegate != null) {
                delegate.endElement(uri, localName, qName);
                delegateDepth--;
                if (delegateDepth == 0) {
                    delegate.endDocument();
                    if (delegate instanceof ContentHandlerFactory.ObjectSource) {
                        Object obj = ((ContentHandlerFactory.ObjectSource)delegate).getObject();
                        if (inForeignObject) {
                            this.foreignObject = (Document)obj;
                        } else {
                            handleExternallyGeneratedObject(obj);
                        }
                    }
                    delegate = null; //Sub-document is processed, return to normal processing
                }
            } else {
                if (NAMESPACE.equals(uri)) {
                    ElementHandler elementHandler = (ElementHandler)elementHandlers.get(localName);
                    if (elementHandler != null) {
                        try {
                            elementHandler.endElement();
                        } catch (IFException ife) {
                            handleIFException(ife);
                        }
                        content.setLength(0);
                    }
                    ignoreCharacters = true;
                } else {
                    if (log.isTraceEnabled()) {
                        log.trace("Ignoring " + localName + " in namespace: " + uri);
                    }
                }
            }
        }

        // ============== Element handlers for the intermediate format =============

        private static interface ElementHandler {
            void startElement(Attributes attributes) throws IFException, SAXException;
            void endElement() throws IFException;
            boolean ignoreCharacters();
        }

        private abstract class AbstractElementHandler implements ElementHandler {

            public void startElement(Attributes attributes) throws IFException, SAXException {
                //nop
            }

            public void endElement() throws IFException {
                //nop
            }

            public boolean ignoreCharacters() {
                return true;
            }
        }

        private class DocumentHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                documentHandler.startDocument();
            }

            public void endElement() throws IFException {
                documentHandler.endDocument();
            }

        }

        private class DocumentHeaderHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                documentHandler.startDocumentHeader();
            }

            public void endElement() throws IFException {
                documentHandler.endDocumentHeader();
            }

        }

        private class DocumentTrailerHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                documentHandler.startDocumentTrailer();
            }

            public void endElement() throws IFException {
                documentHandler.endDocumentTrailer();
            }

        }

        private class PageSequenceHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                String id = attributes.getValue("id");
                String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
                if (xmllang != null) {
                    documentHandler.getContext().setLanguage(
                            XMLUtil.convertRFC3066ToLocale(xmllang));
                }
                Map foreignAttributes = getForeignAttributes(lastAttributes);
                establishForeignAttributes(foreignAttributes);
                documentHandler.startPageSequence(id);
                resetForeignAttributes();
            }

            public void endElement() throws IFException {
                documentHandler.endPageSequence();
                documentHandler.getContext().setLanguage(null);
            }

        }

        private class PageHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                int index = Integer.parseInt(attributes.getValue("index"));
                String name = attributes.getValue("name");
                String pageMasterName = attributes.getValue("page-master-name");
                int width = Integer.parseInt(attributes.getValue("width"));
                int height = Integer.parseInt(attributes.getValue("height"));
                Map foreignAttributes = getForeignAttributes(lastAttributes);
                establishForeignAttributes(foreignAttributes);
                documentHandler.startPage(index, name, pageMasterName,
                        new Dimension(width, height));
                resetForeignAttributes();
            }

            public void endElement() throws IFException {
                documentHandler.endPage();
            }

        }

        private class PageHeaderHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                documentHandler.startPageHeader();
            }

            public void endElement() throws IFException {
                documentHandler.endPageHeader();
            }

        }

        private class PageContentHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                painter = documentHandler.startPageContent();
            }

            public void endElement() throws IFException {
                painter = null;
                documentHandler.endPageContent();
            }

        }

        private class PageTrailerHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                documentHandler.startPageTrailer();
            }

            public void endElement() throws IFException {
                documentHandler.endPageTrailer();
            }

        }

        private class ViewportHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                String transform = attributes.getValue("transform");
                AffineTransform[] transforms
                    = AffineTransformArrayParser.createAffineTransform(transform);
                int width = Integer.parseInt(attributes.getValue("width"));
                int height = Integer.parseInt(attributes.getValue("height"));
                Rectangle clipRect = XMLUtil.getAttributeAsRectangle(attributes, "clip-rect");
                painter.startViewport(transforms, new Dimension(width, height), clipRect);
            }

            public void endElement() throws IFException {
                painter.endViewport();
            }

        }

        private class GroupHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                String transform = attributes.getValue("transform");
                AffineTransform[] transforms
                    = AffineTransformArrayParser.createAffineTransform(transform);
                painter.startGroup(transforms);
            }

            public void endElement() throws IFException {
                painter.endGroup();
            }

        }

        private class FontHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                String family = attributes.getValue("family");
                String style = attributes.getValue("style");
                Integer weight = XMLUtil.getAttributeAsInteger(attributes, "weight");
                String variant = attributes.getValue("variant");
                Integer size = XMLUtil.getAttributeAsInteger(attributes, "size");
                Color color;
                try {
                    color = getAttributeAsColor(attributes, "color");
                } catch (PropertyException pe) {
                    throw new IFException("Error parsing the color attribute", pe);
                }
                painter.setFont(family, style, weight, variant, size, color);
            }

        }

        private class TextHandler extends AbstractElementHandler {

            public void endElement() throws IFException {
                int x = Integer.parseInt(lastAttributes.getValue("x"));
                int y = Integer.parseInt(lastAttributes.getValue("y"));
                String s = lastAttributes.getValue("letter-spacing");
                int letterSpacing = (s != null ? Integer.parseInt(s) : 0);
                s = lastAttributes.getValue("word-spacing");
                int wordSpacing = (s != null ? Integer.parseInt(s) : 0);
                int[] dx = XMLUtil.getAttributeAsIntArray(lastAttributes, "dx");
                setStructurePointer(lastAttributes);
                painter.drawText(x, y, letterSpacing, wordSpacing, dx, content.toString());
                resetStructurePointer();
            }

            public boolean ignoreCharacters() {
                return false;
            }

        }

        private class ClipRectHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                int x = Integer.parseInt(attributes.getValue("x"));
                int y = Integer.parseInt(attributes.getValue("y"));
                int width = Integer.parseInt(attributes.getValue("width"));
                int height = Integer.parseInt(attributes.getValue("height"));
                painter.clipRect(new Rectangle(x, y, width, height));
            }

        }

        private class RectHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                int x = Integer.parseInt(attributes.getValue("x"));
                int y = Integer.parseInt(attributes.getValue("y"));
                int width = Integer.parseInt(attributes.getValue("width"));
                int height = Integer.parseInt(attributes.getValue("height"));
                Color fillColor;
                try {
                    fillColor = getAttributeAsColor(attributes, "fill");
                } catch (PropertyException pe) {
                    throw new IFException("Error parsing the fill attribute", pe);
                }
                painter.fillRect(new Rectangle(x, y, width, height), fillColor);
            }

        }

        private class LineHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                int x1 = Integer.parseInt(attributes.getValue("x1"));
                int y1 = Integer.parseInt(attributes.getValue("y1"));
                int x2 = Integer.parseInt(attributes.getValue("x2"));
                int y2 = Integer.parseInt(attributes.getValue("y2"));
                int width = Integer.parseInt(attributes.getValue("stroke-width"));
                Color color;
                try {
                    color = getAttributeAsColor(attributes, "color");
                } catch (PropertyException pe) {
                    throw new IFException("Error parsing the fill attribute", pe);
                }
                RuleStyle style = RuleStyle.valueOf(attributes.getValue("style"));
                painter.drawLine(new Point(x1, y1), new Point(x2, y2), width, color, style);
            }

        }

        private static final String[] SIDES = new String[] {"before", "after", "start", "end"};

        private class BorderRectHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                int x = Integer.parseInt(attributes.getValue("x"));
                int y = Integer.parseInt(attributes.getValue("y"));
                int width = Integer.parseInt(attributes.getValue("width"));
                int height = Integer.parseInt(attributes.getValue("height"));
                BorderProps[] borders = new BorderProps[4];
                for (int i = 0; i < 4; i++) {
                    String b = attributes.getValue(SIDES[i]);
                    if (b != null) {
                        borders[i] = BorderProps.valueOf(userAgent, b);
                    }
                }

                painter.drawBorderRect(new Rectangle(x, y, width, height),
                        borders[0], borders[1], borders[2], borders[3]);
            }

        }

        private class ImageHandler extends AbstractElementHandler {

            public void startElement(Attributes attributes) throws IFException {
                inForeignObject = true;
            }

            public void endElement() throws IFException {
                int x = Integer.parseInt(lastAttributes.getValue("x"));
                int y = Integer.parseInt(lastAttributes.getValue("y"));
                int width = Integer.parseInt(lastAttributes.getValue("width"));
                int height = Integer.parseInt(lastAttributes.getValue("height"));
                Map foreignAttributes = getForeignAttributes(lastAttributes);
                establishForeignAttributes(foreignAttributes);
                setStructurePointer(lastAttributes);
                if (foreignObject != null) {
                    painter.drawImage(foreignObject,
                            new Rectangle(x, y, width, height));
                    foreignObject = null;
                } else {
                    String uri = lastAttributes.getValue(
                            XLINK_HREF.getNamespaceURI(), XLINK_HREF.getLocalName());
                    if (uri == null) {
                        throw new IFException("xlink:href is missing on image", null);
                    }
                    painter.drawImage(uri, new Rectangle(x, y, width, height));
                }
                resetForeignAttributes();
                resetStructurePointer();
                inForeignObject = false;
            }

            public boolean ignoreCharacters() {
                return false;
            }
        }


        // ====================================================================

        /**
         * Handles objects created by "sub-parsers" that implement the ObjectSource interface.
         * An example of object handled here are ExtensionAttachments.
         * @param obj the Object to be handled.
         * @throws SAXException if an error occurs while handling the extension object
         */
        protected void handleExternallyGeneratedObject(Object obj) throws SAXException {
            try {
                documentHandler.handleExtensionObject(obj);
            } catch (IFException ife) {
                handleIFException(ife);
            }
        }

        private Color getAttributeAsColor(Attributes attributes, String name)
                    throws PropertyException {
            String s = attributes.getValue(name);
            if (s == null) {
                return null;
            } else {
                return ColorUtil.parseColorString(userAgent, s);
            }
        }

        private static Map getForeignAttributes(Attributes atts) {
            Map foreignAttributes = null;
            for (int i = 0, c = atts.getLength(); i < c; i++) {
                String ns = atts.getURI(i);
                if (ns.length() > 0) {
                    if (handledNamespaces.contains(ns)) {
                        continue;
                    }
                    if (foreignAttributes == null) {
                        foreignAttributes = new java.util.HashMap();
                    }
                    QName qname = new QName(ns, atts.getQName(i));
                    foreignAttributes.put(qname, atts.getValue(i));
                }
            }
            return foreignAttributes;
        }

        private void setStructurePointer(Attributes attributes) {
            String ptr = attributes.getValue("ptr");
            if (ptr != null && ptr.length() > 0) {
                establishStructurePointer(ptr);
            }
        }

        /** {@inheritDoc} */
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (delegate != null) {
                delegate.characters(ch, start, length);
            } else if (!ignoreCharacters) {
                this.content.append(ch, start, length);
            }
        }
    }
}
