/*
 * 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.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;

import javax.xml.transform.dom.DOMSource;

import org.w3c.dom.Document;

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

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
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.image.loader.util.ImageUtil;

import org.apache.fop.ResourceEventProducer;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.truetype.SVGGlyphData;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.ImageHandlerRegistry;
import org.apache.fop.render.ImageHandlerUtil;
import org.apache.fop.render.RenderingContext;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;

/**
 * Abstract base class for IFPainter implementations.
 */
public abstract class AbstractIFPainter<T extends IFDocumentHandler> implements IFPainter {

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

    /** non-URI that can be used in feedback messages that an image is an instream-object */
    protected static final String INSTREAM_OBJECT_URI = "(instream-object)";

    /** Holds the intermediate format state */
    protected IFState state;

    private final T documentHandler;

    /**
     * Default constructor.
     */
    public AbstractIFPainter(T documentHandler) {
        this.documentHandler = documentHandler;
    }

    protected String getFontKey(FontTriplet triplet) throws IFException {
        String key = getFontInfo().getInternalFontKey(triplet);
        if (key == null) {
            throw new IFException("The font triplet is not available: \"" + triplet + "\" "
                    + "for the MIME type: \"" + documentHandler.getMimeType() + "\"");
        }
        return key;
    }

    /**
     * Returns the intermediate format context object.
     * @return the context object
     */
    public IFContext getContext() {
        return documentHandler.getContext();
    }

    protected FontInfo getFontInfo() {
        return documentHandler.getFontInfo();
    }

    protected T getDocumentHandler() {
        return documentHandler;
    }

    /**
     * Returns the user agent.
     * @return the user agent
     */
    protected FOUserAgent getUserAgent() {
        return getContext().getUserAgent();
    }

    private AffineTransform combine(AffineTransform[] transforms) {
        AffineTransform at = new AffineTransform();
        for (AffineTransform transform : transforms) {
            at.concatenate(transform);
        }
        return at;
    }

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

    /** {@inheritDoc} */
    public void startGroup(AffineTransform[] transforms, String layer) throws IFException {
        startGroup(combine(transforms), layer);
    }

    /**
     * Creates a new RenderingContext instance.
     * @return the new rendering context.
     */
    protected abstract RenderingContext createRenderingContext();

    /**
     * Loads a preloaded image and draws it using a suitable image handler.
     * @param info the information object of the preloaded image
     * @param rect the rectangle in which to paint the image
     * @throws ImageException if there's an error while processing the image
     * @throws IOException if there's an I/O error while loading the image
     */
    protected void drawImageUsingImageHandler(ImageInfo info, Rectangle rect)
                    throws ImageException, IOException {
        ImageManager manager = getUserAgent().getImageManager();
        ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
        ImageHandlerRegistry imageHandlerRegistry = getUserAgent().getImageHandlerRegistry();

        //Load and convert the image to a supported format
        RenderingContext context = createRenderingContext();
        Map hints = createDefaultImageProcessingHints(sessionContext);
        context.putHints(hints);

        ImageFlavor[] flavors = imageHandlerRegistry.getSupportedFlavors(context);
        info.getCustomObjects().put("warningincustomobject", true);
        org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
                    info, flavors,
                    hints, sessionContext);

        if (info.getCustomObjects().get("warning") != null) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageWarning(this, (String)info.getCustomObjects().get("warning"));
        }

        try {
            drawImage(img, rect, context);
        } catch (IOException ioe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageWritingError(this, ioe);
        }
    }

    /**
     * Creates the default map of processing hints for the image loading framework.
     * @param sessionContext the session context for access to resolution information
     * @return the default processing hints
     */
    protected Map createDefaultImageProcessingHints(ImageSessionContext sessionContext) {
        Map hints = ImageUtil.getDefaultHints(sessionContext);

        //Transfer common foreign attributes to hints
        Object conversionMode = getContext().getForeignAttribute(ImageHandlerUtil.CONVERSION_MODE);
        if (conversionMode != null) {
            hints.put(ImageHandlerUtil.CONVERSION_MODE, conversionMode);
        }
        hints.put("page-number", documentHandler.getContext().getPageNumber());
        return hints;
    }

    /**
     * Draws an image using a suitable image handler.
     * @param image the image to be painted (it needs to of a supported image flavor)
     * @param rect the rectangle in which to paint the image
     * @param context a suitable rendering context
     * @throws IOException in case of an I/O error while handling/writing the image
     * @throws ImageException if an error occurs while converting the image to a suitable format
     */
    protected void drawImage(Image image, Rectangle rect,
            RenderingContext context) throws IOException, ImageException {
        drawImage(image, rect, context, false, null);
    }

    /**
     * Draws an image using a suitable image handler.
     * @param image the image to be painted (it needs to of a supported image flavor)
     * @param rect the rectangle in which to paint the image
     * @param context a suitable rendering context
     * @param convert true to run the image through image conversion if that is necessary
     * @param additionalHints additional image processing hints
     * @throws IOException in case of an I/O error while handling/writing the image
     * @throws ImageException if an error occurs while converting the image to a suitable format
     */
    protected void drawImage(Image image, Rectangle rect,
            RenderingContext context, boolean convert, Map additionalHints)
                    throws IOException, ImageException {
        ImageManager manager = getUserAgent().getImageManager();
        ImageHandlerRegistry imageHandlerRegistry = getUserAgent().getImageHandlerRegistry();

        Image effImage;
        context.putHints(additionalHints);
        if (convert) {
            Map hints = createDefaultImageProcessingHints(getUserAgent().getImageSessionContext());
            if (additionalHints != null) {
                hints.putAll(additionalHints);
            }
            effImage = manager.convertImage(image,
                    imageHandlerRegistry.getSupportedFlavors(context), hints);
        } else {
            effImage = image;
        }

        //First check for a dynamically registered handler
        ImageHandler handler = imageHandlerRegistry.getHandler(context, effImage);
        if (handler == null) {
            throw new UnsupportedOperationException(
                    "No ImageHandler available for image: "
                        + effImage.getInfo() + " (" + effImage.getClass().getName() + ")");
        }

        if (log.isTraceEnabled()) {
            log.trace("Using ImageHandler: " + handler.getClass().getName());
        }
        context.putHint("fontinfo", getFontInfo());
        handler.handleImage(context, effImage, rect);
    }

    /**
     * Returns an ImageInfo instance for the given URI. If there's an error, null is returned.
     * The caller can assume that any exceptions have already been handled properly. The caller
     * simply skips painting anything in this case.
     * @param uri the URI identifying the image
     * @return the ImageInfo instance or null if there has been an error.
     */
    protected ImageInfo getImageInfo(String uri) {
        ImageManager manager = getUserAgent().getImageManager();
        try {
            ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
            return manager.getImageInfo(uri, sessionContext);
        } catch (ImageException ie) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageError(this, uri, ie, null);
        } catch (FileNotFoundException fe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageNotFound(this, uri, fe, null);
        } catch (IOException ioe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageIOError(this, uri, ioe, null);
        }
        return null;
    }

    /**
     * Default drawing method for handling an image referenced by a URI.
     * @param uri the image's URI
     * @param rect the rectangle in which to paint the image
     */
    protected void drawImageUsingURI(String uri, Rectangle rect) {
        ImageManager manager = getUserAgent().getImageManager();
        ImageInfo info = null;
        try {
            ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
            info = manager.getImageInfo(uri, sessionContext);

            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);
        }
    }

    /**
     * Default drawing method for handling a foreign object in the form of a DOM document.
     * @param doc the DOM document containing the foreign object
     * @param rect the rectangle in which to paint the image
     */
    protected void drawImageUsingDocument(Document doc, Rectangle rect) {
        ImageManager manager = getUserAgent().getImageManager();
        ImageInfo info = null;
        try {
            info = manager.preloadImage(null, new DOMSource(doc));

            drawImageUsingImageHandler(info, rect);
        } catch (ImageException ie) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageError(this,
                    (info != null ? info.toString() : INSTREAM_OBJECT_URI), ie, null);
        } catch (FileNotFoundException fe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageNotFound(this,
                    (info != null ? info.toString() : INSTREAM_OBJECT_URI), fe, null);
        } catch (IOException ioe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageIOError(this,
                    (info != null ? info.toString() : INSTREAM_OBJECT_URI), ioe, null);
        }
    }

    /** {@inheritDoc} */
    public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom,
            BorderProps left, BorderProps right, Color innerBackgroundColor) throws IFException {
        if (top != null) {
            Rectangle b = new Rectangle(
                    rect.x, rect.y,
                    rect.width, top.width);
            fillRect(b, top.color);
        }
        if (right != null) {
            Rectangle b = new Rectangle(
                    rect.x + rect.width - right.width, rect.y,
                    right.width, rect.height);
            fillRect(b, right.color);
        }
        if (bottom != null) {
            Rectangle b = new Rectangle(
                    rect.x, rect.y + rect.height - bottom.width,
                    rect.width, bottom.width);
            fillRect(b, bottom.color);
        }
        if (left != null) {
            Rectangle b = new Rectangle(
                    rect.x, rect.y,
                    left.width, rect.height);
            fillRect(b, left.color);
        }
    }

    /**
     * Indicates whether the given border segments (if present) have only solid borders, i.e.
     * could be painted in a simplified fashion keeping the output file smaller.
     * @param top the border segment on the top edge
     * @param bottom the border segment on the bottom edge
     * @param left the border segment on the left edge
     * @param right the border segment on the right edge
     * @return true if any border segment has a non-solid border style
     */
    protected boolean hasOnlySolidBorders(BorderProps top, BorderProps bottom,
            BorderProps left, BorderProps right) {
        if (top != null && top.style != Constants.EN_SOLID) {
            return false;
        }
        if (bottom != null && bottom.style != Constants.EN_SOLID) {
            return false;
        }
        if (left != null && left.style != Constants.EN_SOLID) {
            return false;
        }
        if (right != null && right.style != Constants.EN_SOLID) {
            return false;
        }
        return true;
    }

    /** {@inheritDoc} */
    public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
            throws IFException {
        Rectangle rect = getLineBoundingBox(start, end, width);
        fillRect(rect, color);
    }

    /**
     * Calculates the bounding box for a line. Currently, only horizontal and vertical lines
     * are needed and supported.
     * @param start the starting point of the line (coordinates in mpt)
     * @param end the ending point of the line (coordinates in mpt)
     * @param width the line width (in mpt)
     * @return the bounding box (coordinates in mpt)
     */
    protected Rectangle getLineBoundingBox(Point start, Point end, int width) {
        if (start.y == end.y) {
            int topy = start.y - width / 2;
            return new Rectangle(
                    start.x, topy,
                    end.x - start.x, width);
        } else if (start.x == end.y) {
            int leftx = start.x - width / 2;
            return new Rectangle(
                    leftx, start.x,
                    width, end.y - start.y);
        } else {
            throw new IllegalArgumentException(
                    "Only horizontal or vertical lines are supported at the moment.");
        }
    }

    /** {@inheritDoc} */
    public void setFont(String family, String style, Integer weight, String variant, Integer size,
            Color color) throws IFException {
        if (family != null) {
            state.setFontFamily(family);
        }
        if (style != null) {
            state.setFontStyle(style);
        }
        if (weight != null) {
            state.setFontWeight(weight);
        }
        if (variant != null) {
            state.setFontVariant(variant);
        }
        if (size != null) {
            state.setFontSize(size);
        }
        if (color != null) {
            state.setTextColor(color);
        }
    }

    /**
     * Converts a transformation matrix from millipoints to points.
     * @param transform the transformation matrix (in millipoints)
     * @return the converted transformation matrix (in points)
     */
    public static AffineTransform toPoints(AffineTransform transform) {
        final double[] matrix = new double[6];
        transform.getMatrix(matrix);
        //Convert from millipoints to points
        matrix[4] /= 1000;
        matrix[5] /= 1000;
        return new AffineTransform(matrix);
    }

    /** {@inheritDoc} */
    public boolean isBackgroundRequired(BorderProps bpsBefore, BorderProps bpsAfter,
            BorderProps bpsStart, BorderProps bpsEnd) {
        return true;
    }

    public void drawText(int x, int y, int letterSpacing, int wordSpacing,
                         int[][] dp, String text, boolean nextIsSpace) throws IFException {
        drawText(x, y, letterSpacing, wordSpacing, dp, text);
    }

    protected void drawSVGText(MultiByteFont multiByteFont, FontTriplet triplet, int x, int y, String text,
                               IFState state) throws IFException {
        int sizeMillipoints = state.getFontSize();
        Font font = getFontInfo().getFontInstance(triplet, sizeMillipoints);
        int newx = x;
        for (int i = 0; i < text.length();) {
            int c = text.codePointAt(i);
            SVGGlyphData svg = multiByteFont.getSVG(c);
            if (svg != null) {
                int codePoint = font.mapCodePoint(c);
                String dataURL = svg.getDataURL(multiByteFont.getCapHeight());
                Rectangle boundingBox = multiByteFont.getBoundingBox(codePoint, (int) (sizeMillipoints / 1000f));
                boundingBox.y = y - boundingBox.height - boundingBox.y;
                boundingBox.x = newx;
                boundingBox.width = (int) (sizeMillipoints * svg.scale);
                boundingBox.height = (int) (sizeMillipoints * svg.scale);
                drawImage(dataURL, boundingBox);
            }
            newx += font.getCharWidth(c);
            i += Character.charCount(c);
        }
    }
}
