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

import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import org.apache.batik.ext.awt.LinearGradientPaint;
import org.apache.batik.ext.awt.MultipleGradientPaint;
import org.apache.batik.ext.awt.RadialGradientPaint;

import org.apache.xmlgraphics.java2d.color.ColorUtil;

import org.apache.fop.pdf.PDFDeviceColorSpace;

public final class GradientMaker {

    public interface DoubleFormatter {

        String formatDouble(double d);
    }

    private GradientMaker() { }

    public static Pattern makeLinearGradient(LinearGradientPaint gp,
            AffineTransform baseTransform, AffineTransform transform) {
        Point2D startPoint = gp.getStartPoint();
        Point2D endPoint = gp.getEndPoint();
        List<Double> coords = new java.util.ArrayList<Double>(4);
        coords.add(Double.valueOf(startPoint.getX()));
        coords.add(Double.valueOf(startPoint.getY()));
        coords.add(Double.valueOf(endPoint.getX()));
        coords.add(Double.valueOf(endPoint.getY()));
        return makeGradient(gp, coords, baseTransform, transform);
    }

    public static Pattern makeRadialGradient(RadialGradientPaint gradient,
            AffineTransform baseTransform, AffineTransform transform) {
        double radius = gradient.getRadius();
        Point2D center = gradient.getCenterPoint();
        Point2D focus = gradient.getFocusPoint();
        double dx = focus.getX() - center.getX();
        double dy = focus.getY() - center.getY();
        double d = Math.sqrt(dx * dx + dy * dy);
        if (d > radius) {
            // The center point must be within the circle with
            // radius radius centered at center so limit it to that.
            double scale = (radius * .9999) / d;
            dx *= scale;
            dy *= scale;
        }
        List<Double> coords = new java.util.ArrayList<Double>(6);
        coords.add(Double.valueOf(center.getX() + dx));
        coords.add(Double.valueOf(center.getY() + dy));
        coords.add(Double.valueOf(0));
        coords.add(Double.valueOf(center.getX()));
        coords.add(Double.valueOf(center.getY()));
        coords.add(Double.valueOf(radius));
        return makeGradient(gradient, coords, baseTransform, transform);
    }

    private static Pattern makeGradient(MultipleGradientPaint gradient, List<Double> coords,
            AffineTransform baseTransform, AffineTransform transform) {
        List<Double> matrix = makeTransform(gradient, baseTransform, transform);
        List<Float> bounds = makeBounds(gradient);
        List<Function> functions = makeFunctions(gradient);
        // Gradients are currently restricted to sRGB
        PDFDeviceColorSpace colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
        Function function = new Function(null, null, functions, bounds, null);
        int shadingType = gradient instanceof LinearGradientPaint ? 2 : 3;
        Shading shading = new Shading(shadingType, colorSpace, coords, function);
        return new Pattern(2, shading, matrix);
    }

    private static List<Double> makeTransform(MultipleGradientPaint gradient,
            AffineTransform baseTransform, AffineTransform transform) {
        AffineTransform gradientTransform = new AffineTransform(baseTransform);
        gradientTransform.concatenate(transform);
        gradientTransform.concatenate(gradient.getTransform());
        List<Double> matrix = new ArrayList<Double>(6);
        double[] m = new double[6];
        gradientTransform.getMatrix(m);
        for (double d : m) {
            matrix.add(Double.valueOf(d));
        }
        return matrix;
    }

    private static Color getsRGBColor(Color c) {
        // Color space must be consistent, so convert to sRGB if necessary
        // TODO really?
        return c.getColorSpace().isCS_sRGB() ? c : ColorUtil.toSRGBColor(c);
    }

    private static List<Float> makeBounds(MultipleGradientPaint gradient) {
        float[] fractions = gradient.getFractions();
        List<Float> bounds = new java.util.ArrayList<Float>(fractions.length);
        for (float offset : fractions) {
            if (0f < offset && offset < 1f) {
                bounds.add(offset);
            }
        }
        return bounds;
    }

    private static List<Function> makeFunctions(MultipleGradientPaint gradient) {
        List<Color> colors = makeColors(gradient);
        List<Function> functions = new ArrayList<Function>();
        for (int currentPosition = 0, lastPosition = colors.size() - 1;
                currentPosition < lastPosition;
                currentPosition++) {
            Color currentColor = colors.get(currentPosition);
            Color nextColor = colors.get(currentPosition + 1);
            float[] c0 = currentColor.getColorComponents(null);
            float[] c1 = nextColor.getColorComponents(null);
            Function function = new Function(null, null, c0, c1, 1.0);
            functions.add(function);
        }
        return functions;
    }

    private static List<Color> makeColors(MultipleGradientPaint gradient) {
        Color[] svgColors = gradient.getColors();
        List<Color> gradientColors = new ArrayList<Color>(svgColors.length + 2);
        float[] fractions = gradient.getFractions();
        if (fractions[0] > 0f) {
            gradientColors.add(getsRGBColor(svgColors[0]));
        }
        for (Color c : svgColors) {
            gradientColors.add(getsRGBColor(c));
        }
        if (fractions[fractions.length - 1] < 1f) {
            gradientColors.add(getsRGBColor(svgColors[svgColors.length - 1]));
        }
        return gradientColors;
    }

    static void outputDoubles(StringBuilder out, DoubleFormatter doubleFormatter,
            List<? extends Number> numbers) {
        out.append("[ ");
        for (Number n : numbers) {
            out.append(doubleFormatter.formatDouble(n.doubleValue()));
            out.append(" ");
        }
        out.append("]");
    }

}
