/* ====================================================================
   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.
==================================================================== */

package org.apache.poi.sl.draw;

import java.awt.*;
import java.awt.MultipleGradientPaint.ColorSpaceType;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.geom.*;
import java.awt.image.*;

class PathGradientPaint implements Paint {

    // http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html
    protected final Color colors[];
    protected final float fractions[];
    protected final int capStyle;
    protected final int joinStyle;
    protected final int transparency;

    
    public PathGradientPaint(Color colors[], float fractions[]) {
        this(colors,fractions,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
    }
    
    public PathGradientPaint(Color colors[], float fractions[], int capStyle, int joinStyle) {
        this.colors = colors.clone();
        this.fractions = fractions.clone();
        this.capStyle = capStyle;
        this.joinStyle = joinStyle;

        // determine transparency
        boolean opaque = true;
        for (Color c : colors) {
            if (c != null) {
                opaque = opaque && (c.getAlpha() == 0xff);
            }
        }
        this.transparency = opaque ? OPAQUE : TRANSLUCENT;
    }
    
    public PaintContext createContext(ColorModel cm,
        Rectangle deviceBounds,
        Rectangle2D userBounds,
        AffineTransform transform,
        RenderingHints hints) {
        return new PathGradientContext(cm, deviceBounds, userBounds, transform, hints);
    }
    
    public int getTransparency() {
        return transparency;
    }

    class PathGradientContext implements PaintContext {
        protected final Rectangle deviceBounds;
        protected final Rectangle2D userBounds;
        protected final AffineTransform xform;
        protected final RenderingHints hints;

        /**
         * for POI: the shape will be only known when the subclasses determines the concrete implementation 
         * in the draw/-content method, so we need to postpone the setting/creation as long as possible
         **/
        protected final Shape shape;
        protected final PaintContext pCtx;
        protected final int gradientSteps;
        WritableRaster raster;

        public PathGradientContext(
              ColorModel cm
            , Rectangle deviceBounds
            , Rectangle2D userBounds
            , AffineTransform xform
            , RenderingHints hints
        ) {
            shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE);
            if (shape == null) {
                throw new IllegalPathStateException("PathGradientPaint needs a shape to be set via the rendering hint Drawable.GRADIANT_SHAPE.");
            }

            this.deviceBounds = deviceBounds;
            this.userBounds = userBounds;
            this.xform = xform;
            this.hints = hints;

            gradientSteps = getGradientSteps(shape);

            Point2D start = new Point2D.Double(0, 0);
            Point2D end = new Point2D.Double(gradientSteps, 0);
            LinearGradientPaint gradientPaint = new LinearGradientPaint(start, end, fractions, colors, CycleMethod.NO_CYCLE, ColorSpaceType.SRGB, new AffineTransform());
            
            Rectangle bounds = new Rectangle(0, 0, gradientSteps, 1);
            pCtx = gradientPaint.createContext(cm, bounds, bounds, new AffineTransform(), hints);
        }

        public void dispose() {}

        public ColorModel getColorModel() {
            return pCtx.getColorModel();
        }

        public Raster getRaster(int xOffset, int yOffset, int w, int h) {
            ColorModel cm = getColorModel();
            if (raster == null) createRaster();

            // TODO: eventually use caching here
            WritableRaster childRaster = cm.createCompatibleWritableRaster(w, h);
            Rectangle2D childRect = new Rectangle2D.Double(xOffset, yOffset, w, h);
            if (!childRect.intersects(deviceBounds)) {
                // usually doesn't happen ...
                return childRaster;
            }
            
            Rectangle2D destRect = new Rectangle2D.Double();
            Rectangle2D.intersect(childRect, deviceBounds, destRect);
            int dx = (int)(destRect.getX()-deviceBounds.getX());
            int dy = (int)(destRect.getY()-deviceBounds.getY());
            int dw = (int)destRect.getWidth();
            int dh = (int)destRect.getHeight();
            Object data = raster.getDataElements(dx, dy, dw, dh, null);
            dx = (int)(destRect.getX()-childRect.getX());
            dy = (int)(destRect.getY()-childRect.getY());
            childRaster.setDataElements(dx, dy, dw, dh, data);
            
            return childRaster;
        }

        protected int getGradientSteps(Shape gradientShape) {
            Rectangle rect = gradientShape.getBounds();
            int lower = 1;
            int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0);
            while (lower < upper-1) {
                int mid = lower + (upper - lower) / 2;
                BasicStroke bs = new BasicStroke(mid, capStyle, joinStyle);
                Area area = new Area(bs.createStrokedShape(gradientShape));
                if (area.isSingular()) {
                    upper = mid;
                } else {
                    lower = mid;
                }
            }
            return upper;
        }
        
        
        
        protected void createRaster() {
            ColorModel cm = getColorModel();
            raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight());
            BufferedImage img = new BufferedImage(cm, raster, false, null);
            Graphics2D graphics = img.createGraphics();
            graphics.setRenderingHints(hints);
            graphics.translate(-deviceBounds.getX(), -deviceBounds.getY());
            graphics.transform(xform);

            Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1);
            int rgb[] = new int[cm.getNumComponents()];

            for (int i = gradientSteps-1; i>=0; i--) {
                img2.getPixel(i, 0, rgb);
                Color c = new Color(rgb[0],rgb[1],rgb[2]);
                if (rgb.length == 4) {
                    // it doesn't work to use just a color with transparency ...
                    graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f));                           
                }
                graphics.setStroke(new BasicStroke(i+1, capStyle, joinStyle));
                graphics.setColor(c);
                graphics.draw(shape);
            }
            
            graphics.dispose();
        }
    }
}
