/* ====================================================================
   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;
        this.fractions = fractions;
        this.capStyle = capStyle;
        this.joinStyle = joinStyle;

        // determine transparency
        boolean opaque = true;
        for (int i = 0; i < colors.length; i++){
            opaque = opaque && (colors[i].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 PathGradientPaint.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 shape) {
            Rectangle rect = shape.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(shape));
                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();
        }
    }
}
