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

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;

import org.w3c.dom.Document;

import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

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

import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.xmp.Metadata;

import org.apache.fop.apps.MimeConstants;
import org.apache.fop.events.ResourceEventProducer;
import org.apache.fop.render.ImageHandlerUtil;
import org.apache.fop.render.RenderingContext;
import org.apache.fop.render.intermediate.AbstractIFPainter;
import org.apache.fop.render.intermediate.IFConstants;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFState;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.GenerationHelperContentHandler;
import org.apache.fop.util.XMLConstants;
import org.apache.fop.util.XMLUtil;

/**
 * IFPainter implementation that writes SVG.
 */
public class SVGPainter extends AbstractIFPainter implements SVGConstants {

    /** logging instance */
    private static Log log = LogFactory.getLog(SVGPainter.class);

    private AbstractSVGDocumentHandler parent;

    /** The SAX content handler that receives the generated XML events. */
    protected GenerationHelperContentHandler handler;

    private static final int MODE_NORMAL = 0;
    private static final int MODE_TEXT = 1;

    private int mode = MODE_NORMAL;

    /**
     * Main constructor.
     * @param parent the parent document handler
     * @param contentHandler the target SAX content handler
     */
    public SVGPainter(AbstractSVGDocumentHandler parent,
            GenerationHelperContentHandler contentHandler) {
        super();
        this.parent = parent;
        this.handler = contentHandler;
        this.state = IFState.create();
    }

    /** {@inheritDoc} */
    protected IFContext getContext() {
        return parent.getContext();
    }

    /** {@inheritDoc} */
    public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
            throws IFException {
        startViewport(SVGUtil.formatAffineTransformMptToPt(transform), size, clipRect);
    }

    /** {@inheritDoc} */
    public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect)
            throws IFException {
        startViewport(SVGUtil.formatAffineTransformsMptToPt(transforms), size, clipRect);
    }

    private void startViewport(String transform, Dimension size, Rectangle clipRect)
            throws IFException {
        try {
            establish(MODE_NORMAL);
            AttributesImpl atts = new AttributesImpl();
            if (transform != null && transform.length() > 0) {
                XMLUtil.addAttribute(atts, "transform", transform);
            }
            handler.startElement("g", atts);

            atts.clear();
            XMLUtil.addAttribute(atts, "width", SVGUtil.formatMptToPt(size.width));
            XMLUtil.addAttribute(atts, "height", SVGUtil.formatMptToPt(size.height));
            if (clipRect != null) {
                int[] v = new int[] {
                        clipRect.y,
                        -clipRect.x + size.width - clipRect.width,
                        -clipRect.y + size.height - clipRect.height,
                        clipRect.x};
                int sum = 0;
                for (int i = 0; i < 4; i++) {
                    sum += Math.abs(v[i]);
                }
                if (sum != 0) {
                    StringBuffer sb = new StringBuffer("rect(");
                    sb.append(SVGUtil.formatMptToPt(v[0])).append(',');
                    sb.append(SVGUtil.formatMptToPt(v[1])).append(',');
                    sb.append(SVGUtil.formatMptToPt(v[2])).append(',');
                    sb.append(SVGUtil.formatMptToPt(v[3])).append(')');
                    XMLUtil.addAttribute(atts, "clip", sb.toString());
                }
                XMLUtil.addAttribute(atts, "overflow", "hidden");
            } else {
                XMLUtil.addAttribute(atts, "overflow", "visible");
            }
            handler.startElement("svg", atts);
        } catch (SAXException e) {
            throw new IFException("SAX error in startBox()", e);
        }
    }

    /** {@inheritDoc} */
    public void endViewport() throws IFException {
        try {
            establish(MODE_NORMAL);
            handler.endElement("svg");
            handler.endElement("g");
        } catch (SAXException e) {
            throw new IFException("SAX error in endBox()", e);
        }
    }

    /** {@inheritDoc} */
    public void startGroup(AffineTransform[] transforms) throws IFException {
        startGroup(SVGUtil.formatAffineTransformsMptToPt(transforms));
    }

    /** {@inheritDoc} */
    public void startGroup(AffineTransform transform) throws IFException {
        startGroup(SVGUtil.formatAffineTransformMptToPt(transform));
    }

    private void startGroup(String transform) throws IFException {
        try {
            AttributesImpl atts = new AttributesImpl();
            if (transform != null && transform.length() > 0) {
                XMLUtil.addAttribute(atts, "transform", transform);
            }
            handler.startElement("g", atts);
        } catch (SAXException e) {
            throw new IFException("SAX error in startGroup()", e);
        }
    }

    /** {@inheritDoc} */
    public void endGroup() throws IFException {
        try {
            establish(MODE_NORMAL);
            handler.endElement("g");
        } catch (SAXException e) {
            throw new IFException("SAX error in endGroup()", e);
        }
    }

    /** {@inheritDoc} */
    public void drawImage(String uri, Rectangle rect) throws IFException {
        try {
            establish(MODE_NORMAL);

            ImageManager manager = getUserAgent().getFactory().getImageManager();
            ImageInfo info = null;
            try {
                ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
                info = manager.getImageInfo(uri, sessionContext);

                String mime = info.getMimeType();
                Map foreignAttributes = getContext().getForeignAttributes();
                String conversionMode = (String)foreignAttributes.get(
                        ImageHandlerUtil.CONVERSION_MODE);
                if ("reference".equals(conversionMode)
                        && (MimeConstants.MIME_GIF.equals(mime)
                        || MimeConstants.MIME_JPEG.equals(mime)
                        || MimeConstants.MIME_PNG.equals(mime)
                        || MimeConstants.MIME_SVG.equals(mime))) {
                    //Just reference the image
                    //TODO Some additional URI rewriting might be necessary
                    AttributesImpl atts = new AttributesImpl();
                    XMLUtil.addAttribute(atts, IFConstants.XLINK_HREF, uri);
                    XMLUtil.addAttribute(atts, "x", SVGUtil.formatMptToPt(rect.x));
                    XMLUtil.addAttribute(atts, "y", SVGUtil.formatMptToPt(rect.y));
                    XMLUtil.addAttribute(atts, "width", SVGUtil.formatMptToPt(rect.width));
                    XMLUtil.addAttribute(atts, "height", SVGUtil.formatMptToPt(rect.height));
                    handler.element("image", atts);
                } else {
                    drawImageUsingImageHandler(info, rect);
                }
            } catch (ImageException ie) {
                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                        getUserAgent().getEventBroadcaster());
                eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
            } catch (FileNotFoundException fe) {
                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                        getUserAgent().getEventBroadcaster());
                eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
            } catch (IOException ioe) {
                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                        getUserAgent().getEventBroadcaster());
                eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
            }
        } catch (SAXException e) {
            throw new IFException("SAX error in drawImage()", e);
        }
    }

    /** {@inheritDoc} */
    public void drawImage(Document doc, Rectangle rect) throws IFException {
        try {
            establish(MODE_NORMAL);

            drawImageUsingDocument(doc, rect);
        } catch (SAXException e) {
            throw new IFException("SAX error in drawImage()", e);
        }
    }

    /** {@inheritDoc} */
    protected RenderingContext createRenderingContext() {
        SVGRenderingContext svgContext = new SVGRenderingContext(
                getUserAgent(), handler);
        return svgContext;
    }

    private static String toString(Paint paint) {
        //TODO Paint serialization: Fine-tune and extend!
        if (paint instanceof Color) {
            return ColorUtil.colorToString((Color)paint);
        } else {
            throw new UnsupportedOperationException("Paint not supported: " + paint);
        }
    }

    /** {@inheritDoc} */
    public void clipRect(Rectangle rect) throws IFException {
        //TODO Implement me!!!
    }

    /** {@inheritDoc} */
    public void fillRect(Rectangle rect, Paint fill) throws IFException {
        if (fill == null) {
            return;
        }
        try {
            establish(MODE_NORMAL);
            AttributesImpl atts = new AttributesImpl();
            XMLUtil.addAttribute(atts, "x", SVGUtil.formatMptToPt(rect.x));
            XMLUtil.addAttribute(atts, "y", SVGUtil.formatMptToPt(rect.y));
            XMLUtil.addAttribute(atts, "width", SVGUtil.formatMptToPt(rect.width));
            XMLUtil.addAttribute(atts, "height", SVGUtil.formatMptToPt(rect.height));
            if (fill != null) {
                XMLUtil.addAttribute(atts, "fill", toString(fill));
            }
            /* disabled
            if (stroke != null) {
                XMLUtil.addAttribute(atts, "stroke", toString(stroke));
            }*/
            handler.element("rect", atts);
        } catch (SAXException e) {
            throw new IFException("SAX error in fillRect()", e);
        }
    }

    /** {@inheritDoc} */
    public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
            BorderProps start, BorderProps end) throws IFException {
        // TODO Auto-generated method stub
    }

    /** {@inheritDoc} */
    public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
            throws IFException {
        try {
            establish(MODE_NORMAL);
            AttributesImpl atts = new AttributesImpl();
            XMLUtil.addAttribute(atts, "x1", SVGUtil.formatMptToPt(start.x));
            XMLUtil.addAttribute(atts, "y1", SVGUtil.formatMptToPt(start.y));
            XMLUtil.addAttribute(atts, "x2", SVGUtil.formatMptToPt(end.x));
            XMLUtil.addAttribute(atts, "y2", SVGUtil.formatMptToPt(end.y));
            XMLUtil.addAttribute(atts, "stroke-width", toString(color));
            XMLUtil.addAttribute(atts, "fill", toString(color));
            //TODO Handle style parameter
            handler.element("line", atts);
        } catch (SAXException e) {
            throw new IFException("SAX error in drawLine()", e);
        }
    }

    /** {@inheritDoc} */
    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text)
                throws IFException {
        try {
            establish(MODE_TEXT);
            AttributesImpl atts = new AttributesImpl();
            XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
            XMLUtil.addAttribute(atts, "x", SVGUtil.formatMptToPt(x));
            XMLUtil.addAttribute(atts, "y", SVGUtil.formatMptToPt(y));
            if (letterSpacing != 0) {
                XMLUtil.addAttribute(atts, "letter-spacing", SVGUtil.formatMptToPt(letterSpacing));
            }
            if (wordSpacing != 0) {
                XMLUtil.addAttribute(atts, "word-spacing", SVGUtil.formatMptToPt(wordSpacing));
            }
            if (dx != null) {
                XMLUtil.addAttribute(atts, "dx", SVGUtil.formatMptArrayToPt(dx));
            }
            handler.startElement("text", atts);
            char[] chars = text.toCharArray();
            handler.characters(chars, 0, chars.length);
            handler.endElement("text");
        } catch (SAXException e) {
            throw new IFException("SAX error in setFont()", e);
        }
    }

    private void leaveTextMode() throws SAXException {
        assert this.mode == MODE_TEXT;
        handler.endElement("g");
        this.mode = MODE_NORMAL;
    }

    private void establish(int newMode) throws SAXException {
        switch (newMode) {
        case MODE_TEXT:
            enterTextMode();
            break;
        default:
            if (this.mode == MODE_TEXT) {
                leaveTextMode();
            }
        }
    }

    private void enterTextMode() throws SAXException {
        if (state.isFontChanged() && this.mode == MODE_TEXT) {
            leaveTextMode();
        }
        if (this.mode != MODE_TEXT) {
            startTextGroup();
            this.mode = MODE_TEXT;
        }
    }

    private void startTextGroup() throws SAXException {
        AttributesImpl atts = new AttributesImpl();
        XMLUtil.addAttribute(atts, "font-family", state.getFontFamily());
        XMLUtil.addAttribute(atts, "font-style", state.getFontStyle());
        XMLUtil.addAttribute(atts, "font-weight", Integer.toString(state.getFontWeight()));
        XMLUtil.addAttribute(atts, "font-variant", state.getFontVariant());
        XMLUtil.addAttribute(atts, "font-size", SVGUtil.formatMptToPt(state.getFontSize()));
        XMLUtil.addAttribute(atts, "fill", toString(state.getTextColor()));
        handler.startElement("g", atts);
        state.resetFontChanged();
    }

    /** {@inheritDoc} */
    public void handleExtensionObject(Object extension) throws IFException {
        if (extension instanceof Metadata) {
            Metadata meta = (Metadata)extension;
            try {
                establish(MODE_NORMAL);
                handler.startElement("metadata");
                meta.toSAX(this.handler);
                handler.endElement("metadata");
            } catch (SAXException e) {
                throw new IFException("SAX error while handling extension object", e);
            }
        } else {
            throw new UnsupportedOperationException(
                    "Don't know how to handle extension object: " + extension);
        }
    }

}
