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

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.PaintContext;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferInt;
import java.awt.image.ImageObserver;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSInteger;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.pdmodel.common.function.PDFunction;
import org.apache.pdfbox.pdmodel.common.function.PDFunctionType0;
import org.apache.pdfbox.pdmodel.common.function.PDFunctionType2;
import org.apache.pdfbox.pdmodel.common.function.PDFunctionType3;
import org.apache.pdfbox.pdmodel.graphics.shading.AxialShadingContext;
import org.apache.pdfbox.pdmodel.graphics.shading.AxialShadingPaint;
import org.apache.pdfbox.pdmodel.graphics.shading.RadialShadingContext;
import org.apache.pdfbox.pdmodel.graphics.shading.RadialShadingPaint;
import org.apache.pdfbox.util.Matrix;

import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.io.TempResourceURIGenerator;
import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSResource;

import org.apache.fop.pdf.PDFDeviceColorSpace;
import org.apache.fop.render.gradient.Function;
import org.apache.fop.render.gradient.GradientMaker;
import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
import org.apache.fop.render.gradient.Pattern;
import org.apache.fop.render.gradient.Shading;
import org.apache.fop.render.ps.Gradient;
import org.apache.fop.render.ps.PSDocumentHandler;
import org.apache.fop.render.ps.PSImageUtils;

public class PSPDFGraphics2D extends PSGraphics2D {
    private boolean clearRect;

    public PSPDFGraphics2D(boolean textAsShapes) {
        super(textAsShapes);
    }

    public PSPDFGraphics2D(PSGraphics2D g) {
        super(g);
    }

    public PSPDFGraphics2D(boolean textAsShapes, PSGenerator gen) {
        super(textAsShapes, gen);
    }

    public void clearRect(int x, int y, int width, int height) {
        if (clearRect) {
            super.clearRect(x, y, width, height);
        }
        clearRect = true;
    }

    private final GradientMaker.DoubleFormatter doubleFormatter = new DoubleFormatter() {

        public String formatDouble(double d) {
            return getPSGenerator().formatDouble(d);
        }
    };

    protected void applyPaint(Paint paint, boolean fill) {
        preparePainting();
        if (paint instanceof AxialShadingPaint || paint instanceof RadialShadingPaint) {
            PaintContext paintContext = paint.createContext(null, new Rectangle(), null, new AffineTransform(),
                    getRenderingHints());
            int deviceColorSpace = PDFDeviceColorSpace.DEVICE_RGB;
            if (paint instanceof AxialShadingPaint) {
                try {
                    AxialShadingContext asc = (AxialShadingContext) paintContext;
                    float[] fCoords = asc.getCoords();
                    transformCoords(fCoords, paint, true);
                    PDFunction function = asc.getFunction();
                    Function targetFT = getFunction(function);
                    if (targetFT != null) {
                        if (targetFT.getFunctions().size() == 5
                                && targetFT.getFunctions().get(0).getFunctionType() == 0) {
                            return;
                        }
                        List<Double> dCoords = floatArrayToDoubleList(fCoords);
                        PDFDeviceColorSpace colSpace = new PDFDeviceColorSpace(deviceColorSpace);
                        Shading shading = new Shading(2, colSpace, dCoords, targetFT);
                        Pattern pattern = new Pattern(2, shading, null);
                        gen.write(Gradient.outputPattern(pattern, doubleFormatter));
                    }
                } catch (IOException ioe) {
                    handleIOException(ioe);
                }
            } else if (paint instanceof RadialShadingPaint) {
                try {
                    RadialShadingContext rsc = (RadialShadingContext) paintContext;
                    float[] fCoords = rsc.getCoords();
                    transformCoords(fCoords, paint, false);
                    PDFunction function = rsc.getFunction();
                    Function targetFT3 = getFunction(function);
                    List<Double> dCoords = floatArrayToDoubleList(fCoords);
                    PDFDeviceColorSpace colSpace = new PDFDeviceColorSpace(deviceColorSpace);
                    Shading shading = new Shading(3, colSpace, dCoords, targetFT3);
                    Pattern pattern = new Pattern(2, shading, null);
                    gen.write(Gradient.outputPattern(pattern, doubleFormatter));
                } catch (IOException ioe) {
                    handleIOException(ioe);
                }
            }
        } else if (paint.getClass().getSimpleName().equals("TilingPaint")) {
            try {
                Field f = paint.getClass().getDeclaredField("paint");
                f.setAccessible(true);
                TexturePaint texturePaint = (TexturePaint) f.get(paint);
                f = paint.getClass().getDeclaredField("patternMatrix");
                f.setAccessible(true);
                Matrix matrix = (Matrix) f.get(paint);
                Rectangle2D rect = getTransformedRect(matrix, texturePaint.getAnchorRect());
                texturePaint = new TexturePaint(texturePaint.getImage(), rect);
                super.applyPaint(texturePaint, fill);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static Rectangle2D getTransformedRect(Matrix matrix, Rectangle2D anchorRect) {
        double x = anchorRect.getX();
        double y = anchorRect.getY();
        double width = anchorRect.getWidth();
        double height = anchorRect.getHeight();
        AffineTransform at = matrix.createAffineTransform();
        Point2D p1 = new Point2D.Double(x, y);
        Point2D p2 = new Point2D.Double(x + width, y + height);
        at.transform(p1, p1);
        at.transform(p2, p2);
        Rectangle2D rectangle = new Rectangle2D.Float(
                (float) Math.min(p1.getX(), p2.getX()),
                (float) Math.min(p1.getY(), p2.getY()),
                (float) Math.abs(width),
                (float) Math.abs(height));
        return rectangle;
    }

    private void transformCoords(float[] coords, Paint paint, boolean axialShading) {
        try {
            Field f = paint.getClass().getDeclaredField("matrix");
            f.setAccessible(true);
            Matrix ctm = (Matrix) f.get(paint);
            AffineTransform at = ctm.createAffineTransform();
            if (axialShading) {
                at.transform(coords, 0, coords, 0, 2);
            } else {
                at.transform(coords, 0, coords, 0, 1);
                at.transform(coords, 3, coords, 3, 1);
                coords[2] *= ctm.getScalingFactorX();
                coords[5] *= ctm.getScalingFactorX();
            }

        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    protected static Function getFunction(PDFunction f) throws IOException {
        if (f instanceof PDFunctionType3) {
            PDFunctionType3 sourceFT3 = (PDFunctionType3) f;
            float[] bounds = sourceFT3.getBounds().toFloatArray();
            COSArray sourceFunctions = sourceFT3.getFunctions();
            List<Function> targetFunctions = new ArrayList<Function>();
            for (int j = 0; j < sourceFunctions.size(); j++) {
                targetFunctions.add(getFunction(PDFunction.create(sourceFunctions.get(j))));
            }
            return new Function(null, null, targetFunctions, toList(bounds), null);
        } else if (f instanceof PDFunctionType2) {
            PDFunctionType2 sourceFT2 = (PDFunctionType2) f;
            double interpolation = (double)sourceFT2.getN();
            float[] c0 = sourceFT2.getC0().toFloatArray();
            float[] c1 = sourceFT2.getC1().toFloatArray();
            return new Function(null, null, c0, c1, interpolation);
        } else if (f instanceof PDFunctionType0) {
            COSDictionary s = f.getCOSObject();
            assert s instanceof COSStream;
            COSStream stream = (COSStream) s;
            COSArray domain = (COSArray) s.getDictionaryObject(COSName.DOMAIN);
            COSArray range = (COSArray) s.getDictionaryObject(COSName.RANGE);
            int bits = ((COSInteger)s.getDictionaryObject(COSName.BITS_PER_SAMPLE)).intValue();
            COSArray size = (COSArray) s.getDictionaryObject(COSName.SIZE);
            COSArray encode = getEncode(s);
            byte[] x = IOUtils.toByteArray(stream.getUnfilteredStream());
            for (byte y : x) {
                if (y != 0) {
                    return new Function(floatArrayToDoubleList(domain.toFloatArray()),
                            floatArrayToDoubleList(range.toFloatArray()),
                            floatArrayToDoubleList(encode.toFloatArray()),
                            x,
                            bits,
                            toList(size)
                    );
                }
            }
            return null;
        }
        throw new IOException("Unsupported " + f.toString());
    }

    private static COSArray getEncode(COSDictionary s) {
        COSArray encode = (COSArray) s.getDictionaryObject(COSName.ENCODE);
        if (encode == null) {
            encode = new COSArray();
            COSArray size = (COSArray) s.getDictionaryObject(COSName.SIZE);
            int sizeValuesSize = size.size();
            for (int i = 0; i < sizeValuesSize; i++) {
                encode.add(COSInteger.ZERO);
                encode.add(COSInteger.get(size.getInt(i) - 1));
            }
        }
        return encode;
    }

    private static List<Float> toList(float[] array) {
        List<Float> list = new ArrayList<Float>(array.length);
        for (float f : array) {
            list.add(f);
        }
        return list;
    }

    private static List<Integer> toList(COSArray array) {
        List<Integer> list = new ArrayList<Integer>();
        for (COSBase i : array) {
            list.add(((COSInteger)i).intValue());
        }
        return list;
    }

    private static List<Double> floatArrayToDoubleList(float[] floatArray) {
        List<Double> doubleList = new ArrayList<Double>();
        for (float f : floatArray) {
            doubleList.add((double) f);
        }
        return doubleList;
    }

    @Override
    public boolean drawImage(Image img, int x1, int y1, ImageObserver observer) {
        Color mask = null;
        ColorModel cm = ((BufferedImage)img).getColorModel();
        if (cm.hasAlpha()) {
            mask = Color.WHITE;
        }
        if (gen instanceof PSDocumentHandler.FOPPSGenerator) {
            PSDocumentHandler.FOPPSGenerator fopGen = (PSDocumentHandler.FOPPSGenerator)gen;
            PSDocumentHandler handler = fopGen.getHandler();
            if (handler.getPSUtil().isOptimizeResources()) {
                try {
                    final int width = img.getWidth(observer);
                    final int height = img.getHeight(observer);
                    if (width == -1 || height == -1) {
                        return false;
                    }
                    BufferedImage buf = getImage(width, height, img, observer);
                    if (buf == null) {
                        return false;
                    }
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    DataBufferInt db = (DataBufferInt) buf.getRaster().getDataBuffer();
                    DataOutputStream dos = new DataOutputStream(bos);
                    dos.writeInt(width);
                    dos.writeInt(height);
                    for (int i : db.getData()) {
                        dos.writeInt(i);
                    }
                    String format = DataBufferInt.class.getName();
                    int hash = Arrays.hashCode(bos.toByteArray());
                    URI uri = fopGen.getImages().get(hash);
                    if (uri == null) {
                        uri = new TempResourceURIGenerator("img" + hash + "." + format).generate();
                        fopGen.getImages().put(hash, uri);
                        BufferedOutputStream outputStream = fopGen.getTempStream(uri);
                        outputStream.write(bos.toByteArray());
                        outputStream.close();
                    }
                    PSResource form = handler.getFormForImage(uri.toASCIIString());
                    ImageInfo info = new ImageInfo(uri.toASCIIString(), "image/" + format);
                    ImageSize size = new ImageSize(width, height, handler.getUserAgent().getTargetResolution());
                    size.calcSizeFromPixels();
                    info.setSize(size);
                    float res = handler.getUserAgent().getSourceResolution() / 72;
                    Rectangle rect =
                            new Rectangle(0, 0, (int)(size.getWidthMpt() * res), (int)(size.getHeightMpt() * res));
                    gen.saveGraphicsState();
                    gen.concatMatrix(getTransform());
                    writeClip(getClip());
                    PSImageUtils.drawForm(form, info, rect, gen);
                    gen.restoreGraphicsState();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                return true;
            }
        }
        return super.drawImage(img, x1, y1, observer, mask);
    }

    private BufferedImage getImage(int width, int height, Image img, ImageObserver observer) {
        Dimension size = new Dimension(width, height);
        BufferedImage buf = buildBufferedImage(size);
        Graphics2D g = buf.createGraphics();
        g.setComposite(AlphaComposite.SrcOver);
        g.setBackground(new Color(1, 1, 1, 0));
        g.fillRect(0, 0, width, height);
        g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight()));
        if (!g.drawImage(img, 0, 0, observer)) {
            return null;
        }
        g.dispose();
        return buf;
    }
}
