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

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

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

import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
import org.apache.xmlgraphics.java2d.GraphicContext;
import org.apache.xmlgraphics.java2d.GraphicsConfigurationWithTransparency;
import org.apache.xmlgraphics.java2d.StrokingTextHandler;
import org.apache.xmlgraphics.java2d.TextHandler;
import org.apache.xmlgraphics.util.UnitConv;

import org.apache.fop.afp.goca.GraphicsSetLineType;
import org.apache.fop.afp.modca.GraphicsObject;
import org.apache.fop.afp.modca.ResourceObject;
import org.apache.fop.afp.util.CubicBezierApproximator;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.afp.AFPImageHandlerRenderedImage;
import org.apache.fop.render.afp.AFPRenderingContext;
import org.apache.fop.svg.NativeImageHandler;

/**
 * This is a concrete implementation of {@link AbstractGraphics2D} (and
 * therefore of {@link java.awt.Graphics2D}) which is able to generate GOCA byte
 * codes.
 *
 * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D
 */
public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHandler {

    private static final Log LOG = LogFactory.getLog(AFPGraphics2D.class);

    private static final int X = 0;

    private static final int Y = 1;

    private static final int X1 = 0;

    private static final int Y1 = 1;

    private static final int X2 = 2;

    private static final int Y2 = 3;

    private static final int X3 = 4;

    private static final int Y3 = 5;

    /** graphics object */
    private GraphicsObject graphicsObj;

    /** Fallback text handler */
    protected TextHandler fallbackTextHandler = new StrokingTextHandler();

    /** Custom text handler */
    protected TextHandler customTextHandler;

    /** AFP resource manager */
    private AFPResourceManager resourceManager;

    /** AFP resource info */
    private AFPResourceInfo resourceInfo;

    /** Current AFP state */
    private AFPPaintingState paintingState;

    /** AFP graphics configuration */
    private final GraphicsConfigurationWithTransparency graphicsConfig = new GraphicsConfigurationWithTransparency();

    /** The AFP FontInfo */
    private FontInfo fontInfo;

    /**
     * Main constructor
     *
     * @param textAsShapes
     *            if true, all text is turned into shapes in the convertion. No
     *            text is output.
     * @param paintingState painting state
     * @param resourceManager resource manager
     * @param resourceInfo resource info
     * @param fontInfo font info
     */
    public AFPGraphics2D(boolean textAsShapes, AFPPaintingState paintingState,
            AFPResourceManager resourceManager, AFPResourceInfo resourceInfo,
            FontInfo fontInfo) {
        super(textAsShapes);
        setPaintingState(paintingState);
        setResourceManager(resourceManager);
        setResourceInfo(resourceInfo);
        setFontInfo(fontInfo);
    }

    /**
     * Copy Constructor
     *
     * @param g2d
     *            a AFPGraphics2D whose properties should be copied
     */
    public AFPGraphics2D(AFPGraphics2D g2d) {
        super(g2d);
        this.paintingState = g2d.paintingState;
        this.resourceManager = g2d.resourceManager;
        this.resourceInfo = g2d.resourceInfo;
        this.fontInfo = g2d.fontInfo;

        this.graphicsObj = g2d.graphicsObj;
        this.fallbackTextHandler = g2d.fallbackTextHandler;
        this.customTextHandler = g2d.customTextHandler;
    }

    /**
     * Sets the AFP resource manager
     *
     * @param resourceManager the AFP resource manager
     */
    private void setResourceManager(AFPResourceManager resourceManager) {
        this.resourceManager = resourceManager;
    }

    /**
     * Returns the AFP resource manager associated with this {@link java.awt.Graphics2D} instance.
     * @return the resource manager
     */
    public AFPResourceManager getResourceManager() {
        return this.resourceManager;
    }

    /**
     * Sets the AFP resource info
     *
     * @param resourceInfo the AFP resource info
     */
    private void setResourceInfo(AFPResourceInfo resourceInfo) {
        this.resourceInfo = resourceInfo;
    }

    /**
     * Returns the GOCA graphics object
     *
     * @return the GOCA graphics object
     */
    public GraphicsObject getGraphicsObject() {
        return this.graphicsObj;
    }

    /**
     * Sets the GOCA graphics object
     *
     * @param obj the GOCA graphics object
     */
    public void setGraphicsObject(GraphicsObject obj) {
        this.graphicsObj = obj;
    }

    /**
     * Sets the AFP painting state
     *
     * @param paintingState the AFP painting state
     */
    private void setPaintingState(AFPPaintingState paintingState) {
        this.paintingState = paintingState;
    }

    /**
     * Returns the AFP painting state
     *
     * @return the AFP painting state
     */
    public AFPPaintingState getPaintingState() {
        return this.paintingState;
    }

    /**
     * Sets the FontInfo
     *
     * @param fontInfo the FontInfo
     */
    private void setFontInfo(FontInfo fontInfo) {
        this.fontInfo = fontInfo;
    }

    /**
     * Returns the FontInfo
     *
     * @return the FontInfo
     */
    public FontInfo getFontInfo() {
        return this.fontInfo;
    }

    /**
     * Sets the GraphicContext
     *
     * @param gc
     *            GraphicContext to use
     */
    public void setGraphicContext(GraphicContext gc) {
        this.gc = gc;
    }

    private int getResolution() {
        return this.paintingState.getResolution();
    }

    /**
     * Converts a length value to an absolute value.
     * Please note that this only uses the "ScaleY" factor, so this will result
     * in a bad value should "ScaleX" and "ScaleY" be different.
     * @param length the length
     * @return the absolute length
     */
    public double convertToAbsoluteLength(double length) {
        AffineTransform current = getTransform();
        double mult = getResolution() / (double)UnitConv.IN2PT;
        double factor = -current.getScaleY() / mult;
        return length * factor;
    }

    /**
     * Apply the stroke to the AFP graphics object.
     * This takes the java stroke and outputs the appropriate settings
     * to the AFP graphics object so that the stroke attributes are handled.
     *
     * @param stroke the java stroke
     */
    protected void applyStroke(Stroke stroke) {
        if (stroke instanceof BasicStroke) {
            BasicStroke basicStroke = (BasicStroke) stroke;

            // set line width and correct it; NOTE: apparently we need to correct the width so that the
            // output looks OK since the default with depends on the output device
            float lineWidth = basicStroke.getLineWidth();
            float correction = paintingState.getLineWidthCorrection();
            graphicsObj.setLineWidth(lineWidth * correction);

            //No line join, miter limit and end cap support in GOCA. :-(

            // set line type/style (note: this is an approximation at best!)
            float[] dashArray = basicStroke.getDashArray();
            if (paintingState.setDashArray(dashArray)) {
                byte type = GraphicsSetLineType.DEFAULT; // normally SOLID
                if (dashArray != null) {
                    type = GraphicsSetLineType.DOTTED; // default to plain DOTTED if dashed line
                    // float offset = basicStroke.getDashPhase();
                    if (dashArray.length == 2) {
                        if (dashArray[0] < dashArray[1]) {
                            type = GraphicsSetLineType.SHORT_DASHED;
                        } else if (dashArray[0] > dashArray[1]) {
                            type = GraphicsSetLineType.LONG_DASHED;
                        }
                    } else if (dashArray.length == 4) {
                        if (dashArray[0] > dashArray[1]
                         && dashArray[2] < dashArray[3]) {
                            type = GraphicsSetLineType.DASH_DOT;
                        } else if (dashArray[0] < dashArray[1]
                                && dashArray[2] < dashArray[3]) {
                            type = GraphicsSetLineType.DOUBLE_DOTTED;
                        }
                    } else if (dashArray.length == 6) {
                        if (dashArray[0] > dashArray[1]
                         && dashArray[2] < dashArray[3]
                         && dashArray[4] < dashArray[5]) {
                            type = GraphicsSetLineType.DASH_DOUBLE_DOTTED;
                        }
                    }
                }
                graphicsObj.setLineType(type);
            }
        } else {
            LOG.warn("Unsupported Stroke: " + stroke.getClass().getName());
        }
    }

    /**
     * Apply the java paint to the AFP.
     * This takes the java paint sets up the appropriate AFP commands
     * for the drawing with that paint.
     * Currently this supports the gradients and patterns from batik.
     *
     * @param paint the paint to convert to AFP
     * @param fill true if the paint should be set for filling
     * @return true if the paint is handled natively, false if the paint should be rasterized
     */
    private boolean applyPaint(Paint paint, boolean fill) {
        if (paint instanceof Color) {
            return true;
        }
        LOG.debug("NYI: applyPaint() " + paint + " fill=" + fill);
//      if (paint instanceof TexturePaint) {
//            TexturePaint texturePaint = (TexturePaint)paint;
//            BufferedImage bufferedImage = texturePaint.getImage();
//            AffineTransform at = paintingState.getTransform();
//            int x = (int)Math.round(at.getTranslateX());
//            int y = (int)Math.round(at.getTranslateY());
//            drawImage(bufferedImage, x, y, null);
//      }
        return false;
    }


    /**
     * Handle the Batik drawing event
     *
     * @param shape
     *            the shape to draw
     * @param fill
     *            true if the shape is to be drawn filled
     */
    private void doDrawing(Shape shape, boolean fill) {
        if (!fill) {
            graphicsObj.newSegment();
        }

        graphicsObj.setColor(gc.getColor());

        applyPaint(gc.getPaint(), fill);

        if (fill) {
            graphicsObj.beginArea();
        } else {
            applyStroke(gc.getStroke());
        }

        AffineTransform trans = gc.getTransform();
        PathIterator iter = shape.getPathIterator(trans);
        if (shape instanceof Line2D) {
            double[] dstPts = new double[6];
            iter.currentSegment(dstPts);
            int[] coords = new int[4];
            coords[X1] = (int) Math.round(dstPts[X]);
            coords[Y1] = (int) Math.round(dstPts[Y]);
            iter.next();
            iter.currentSegment(dstPts);
            coords[X2] = (int) Math.round(dstPts[X]);
            coords[Y2] = (int) Math.round(dstPts[Y]);
            graphicsObj.addLine(coords);
        } else if (shape instanceof Rectangle2D) {
            double[] dstPts = new double[6];
            iter.currentSegment(dstPts);
            int[] coords = new int[4];
            coords[X2] = (int) Math.round(dstPts[X]);
            coords[Y2] = (int) Math.round(dstPts[Y]);
            iter.next();
            iter.next();
            iter.currentSegment(dstPts);
            coords[X1] = (int) Math.round(dstPts[X]);
            coords[Y1] = (int) Math.round(dstPts[Y]);
            graphicsObj.addBox(coords);
        } else if (shape instanceof Ellipse2D) {
            double[] dstPts = new double[6];
            Ellipse2D elip = (Ellipse2D) shape;
            double scale = trans.getScaleX();
            double radiusWidth = elip.getWidth() / 2;
            double radiusHeight = elip.getHeight() / 2;
            graphicsObj.setArcParams(
                    (int)Math.round(radiusWidth * scale),
                    (int)Math.round(radiusHeight * scale),
                    0,
                    0
            );
            double[] srcPts = new double[] {elip.getCenterX(), elip.getCenterY()};
            trans.transform(srcPts, 0, dstPts, 0, 1);
            final int mh = 1;
            final int mhr = 0;
            graphicsObj.addFullArc(
                    (int)Math.round(dstPts[X]),
                    (int)Math.round(dstPts[Y]),
                    mh,
                    mhr
            );
        } else {
            processPathIterator(iter);
        }

        if (fill) {
            graphicsObj.endArea();
        }
    }

    /**
     * Processes a path iterator generating the necessary painting operations.
     *
     * @param iter PathIterator to process
     */
    private void processPathIterator(PathIterator iter) {
        double[] dstPts = new double[6];
        double[] currentPosition = new double[2];
        List<Integer> fillets = new ArrayList<Integer>();
        for (int[] openingCoords = new int[2]; !iter.isDone(); iter.next()) {
            switch (iter.currentSegment(dstPts)) {
            case PathIterator.SEG_LINETO:
                flush(fillets);
                graphicsObj.addLine(new int[] {
                        (int)Math.round(dstPts[X]),
                        (int)Math.round(dstPts[Y])
                     }, true);
                currentPosition = new double[]{dstPts[X], dstPts[Y]};
                break;
            case PathIterator.SEG_QUADTO:
                flush(fillets);
                graphicsObj.addFillet(new int[] {
                        (int)Math.round(dstPts[X1]),
                        (int)Math.round(dstPts[Y1]),
                        (int)Math.round(dstPts[X2]),
                        (int)Math.round(dstPts[Y2])
                }, true);
                currentPosition = new double[]{dstPts[X2], dstPts[Y2]};
                break;
            case PathIterator.SEG_CUBICTO:
                double[] cubicCoords = new double[] {currentPosition[0], currentPosition[1],
                    dstPts[X1], dstPts[Y1], dstPts[X2], dstPts[Y2], dstPts[X3], dstPts[Y3]};
                double[][] quadParts = CubicBezierApproximator.fixedMidPointApproximation(
                        cubicCoords);
                if (quadParts.length >= 4) {
                    for (double[] quadPts : quadParts) {
                        if (quadPts != null && quadPts.length == 4) {
                            fillets.add((int) Math.round(quadPts[X1]));
                            fillets.add((int) Math.round(quadPts[Y1]));
                            fillets.add((int) Math.round(quadPts[X2]));
                            fillets.add((int) Math.round(quadPts[Y2]));
                            currentPosition = new double[]{quadPts[X2], quadPts[Y2]};
                        }
                    }
                }
                break;
            case PathIterator.SEG_MOVETO:
                flush(fillets);
                openingCoords = new int[] {
                        (int)Math.round(dstPts[X]),
                        (int)Math.round(dstPts[Y])
                };
                currentPosition = new double[]{dstPts[X], dstPts[Y]};
                graphicsObj.setCurrentPosition(openingCoords);
                break;
            case PathIterator.SEG_CLOSE:
                flush(fillets);
                graphicsObj.addLine(openingCoords, true);
                currentPosition = new double[]{openingCoords[0], openingCoords[1]};
                break;
            default:
                LOG.debug("Unrecognised path iterator type");
                break;
            }
        }
        flush(fillets);
    }

    private void flush(List<Integer> fillets) {
        List<int[]> intList = listToIntLists(fillets);
        for (int[] ints : intList) {
            graphicsObj.addFillet(ints, true);
        }
    }

    private List<int[]> listToIntLists(List<Integer> input) {
        List<int[]> out = new ArrayList<int[]>();
        while (!input.isEmpty()) {
            int[] data = new int[Math.min(100, input.size())];
            for (int i = 0; i < data.length; i++) {
                data[i] = input.remove(0);
            }
            out.add(data);
        }
        return out;
    }

    /** {@inheritDoc} */
    @Override
    public void draw(Shape shape) {
        LOG.debug("draw() shape=" + shape);
        doDrawing(shape, false);
    }

    /** {@inheritDoc} */
    @Override
    public void fill(Shape shape) {
        LOG.debug("fill() shape=" + shape);
        doDrawing(shape, true);
    }

    /**
     * Central handler for IOExceptions for this class.
     *
     * @param ioe
     *            IOException to handle
     */
    public void handleIOException(IOException ioe) {
        // TODO Surely, there's a better way to do this.
        LOG.error(ioe.getMessage());
        ioe.printStackTrace();
    }

    /** {@inheritDoc} */
    @Override
    public void drawString(String str, float x, float y) {
        try {
            if (customTextHandler != null && !textAsShapes) {
                customTextHandler.drawString(this, str, x, y);
            } else {
                fallbackTextHandler.drawString(this, str, x, y);
            }
        } catch (IOException ioe) {
            handleIOException(ioe);
        }
    }

    /** {@inheritDoc} */
    @Override
    public GraphicsConfiguration getDeviceConfiguration() {
        return graphicsConfig;
    }

    /** {@inheritDoc} */
    @Override
    public Graphics create() {
        return new AFPGraphics2D(this);
    }

    /** {@inheritDoc} */
    @Override
    public void dispose() {
        this.graphicsObj = null;
    }

    /** {@inheritDoc} */
    @Override
    public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
        return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), observer);
    }

    private BufferedImage buildBufferedImage(Dimension size) {
        return new BufferedImage(size.width, size.height,
                                 BufferedImage.TYPE_INT_ARGB);
    }

    /**
     * Draws an AWT image into a BufferedImage using an AWT Graphics2D implementation
     *
     * @param img the AWT image
     * @param bufferedImage the AWT buffered image
     * @param width the image width
     * @param height the image height
     * @param observer the image observer
     * @return true if the image was drawn
     */
    private boolean drawBufferedImage(Image img, BufferedImage bufferedImage,
            int width, int height, ImageObserver observer) {

        java.awt.Graphics2D g2d = bufferedImage.createGraphics();
        try {
            g2d.setComposite(AlphaComposite.SrcOver);

            Color color = new Color(1, 1, 1, 0);
            g2d.setBackground(color);
            g2d.setPaint(color);

            g2d.fillRect(0, 0, width, height);

            int imageWidth = bufferedImage.getWidth();
            int imageHeight = bufferedImage.getHeight();
            Rectangle clipRect = new Rectangle(0, 0, imageWidth, imageHeight);
            g2d.clip(clipRect);

            g2d.setComposite(gc.getComposite());

            return g2d.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
        } finally {
            g2d.dispose(); //drawn so dispose immediately to free system resource
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean drawImage(Image img, int x, int y, int width, int height,
            ImageObserver observer) {
        // draw with AWT Graphics2D
        Dimension imageSize = new Dimension(width, height);
        BufferedImage bufferedImage = buildBufferedImage(imageSize);

        boolean drawn = drawBufferedImage(img, bufferedImage, width, height, observer);
        if (drawn) {
            drawRenderedImage(bufferedImage, new AffineTransform());
        }
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
        int imgWidth = img.getWidth();
        int imgHeight = img.getHeight();

        AffineTransform gat = gc.getTransform();
        int graphicsObjectHeight
            = graphicsObj.getObjectEnvironmentGroup().getObjectAreaDescriptor().getHeight();

        double toMillipointFactor = UnitConv.IN2PT * 1000 / (double)paintingState.getResolution();
        double x = gat.getTranslateX();
        double y = -(gat.getTranslateY() - graphicsObjectHeight);
        x = toMillipointFactor * x;
        y = toMillipointFactor * y;
        double w = toMillipointFactor * imgWidth * gat.getScaleX();
        double h = toMillipointFactor * imgHeight * -gat.getScaleY();

        AFPImageHandlerRenderedImage handler = new AFPImageHandlerRenderedImage();
        String uri = null;
        if (resourceManager.getResourceLevelDefaults()
                .getDefaultResourceLevel(ResourceObject.TYPE_GRAPHIC).isPrintFile()) {
            uri = resourceInfo.getUri();
        }
        ImageInfo imageInfo = new ImageInfo(uri, null);
        imageInfo.setSize(new ImageSize(
                img.getWidth(), img.getHeight(), paintingState.getResolution()));
        imageInfo.getSize().calcSizeFromPixels();
        ImageRendered red = new ImageRendered(imageInfo, img, null);
        Rectangle targetPos = new Rectangle(
                (int)Math.round(x),
                (int)Math.round(y),
                (int)Math.round(w),
                (int)Math.round(h));
        AFPRenderingContext context = new AFPRenderingContext(null,
                resourceManager, paintingState, fontInfo, null);
        resourceManager.includeCached = false;
        try {
            handler.handleImage(context, red, targetPos);
        } catch (IOException ioe) {
            handleIOException(ioe);
        }
        resourceManager.includeCached = true;
    }

    /**
     * Sets a custom TextHandler implementation that is responsible for painting
     * text. The default TextHandler paints all text as shapes. A custom
     * implementation can implement text painting using text painting operators.
     *
     * @param handler
     *            the custom TextHandler implementation
     */
    public void setCustomTextHandler(TextHandler handler) {
        this.customTextHandler = handler;
    }

    /** {@inheritDoc} */
    @Override
    public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
        LOG.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform);
    }

    /** {@inheritDoc} */
    @Override
    public FontMetrics getFontMetrics(Font f) {
        LOG.debug("getFontMetrics() NYI: f=" + f);
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public void setXORMode(Color col) {
        LOG.debug("setXORMode() NYI: col=" + col);
    }

    /** {@inheritDoc} */
    public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image,
            float x, float y, float width, float height) {
        LOG.debug("NYI: addNativeImage() " + "image=" + image
                + ",x=" + x + ",y=" + y + ",width=" + width + ",height=" + height);
    }

    /** {@inheritDoc} */
    @Override
    public void copyArea(int x, int y, int width, int height, int dx, int dy) {
        LOG.debug("copyArea() NYI: ");
    }

    public void clearRect(int x, int y, int width, int height) {
    }
}
