/* ====================================================================
   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.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.RadialGradientPaint;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.function.BiFunction;

import org.apache.poi.sl.usermodel.AbstractColorStyle;
import org.apache.poi.sl.usermodel.ColorStyle;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;
import org.apache.poi.sl.usermodel.PaintStyle.PaintModifier;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
import org.apache.poi.sl.usermodel.PlaceableShape;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;


/**
 * This class handles color transformations.
 *
 * @see <a href="https://tips4java.wordpress.com/2009/07/05/hsl-color/">HSL code taken from Java Tips Weblog</a>
 */
public class DrawPaint {
    // HSL code is public domain - see https://tips4java.wordpress.com/contact-us/

    private static final POILogger LOG = POILogFactory.getLogger(DrawPaint.class);

    private static final Color TRANSPARENT = new Color(1f,1f,1f,0f);

    protected PlaceableShape<?,?> shape;

    public DrawPaint(PlaceableShape<?,?> shape) {
        this.shape = shape;
    }

    private static class SimpleSolidPaint implements SolidPaint {
        private final ColorStyle solidColor;

        SimpleSolidPaint(final Color color) {
            if (color == null) {
                throw new NullPointerException("Color needs to be specified");
            }
            this.solidColor = new AbstractColorStyle(){
                    @Override
                    public Color getColor() {
                        return new Color(color.getRed(), color.getGreen(), color.getBlue());
                    }
                    @Override
                    public int getAlpha() { return (int)Math.round(color.getAlpha()*100000./255.); }
                    @Override
                    public int getHueOff() { return -1; }
                    @Override
                    public int getHueMod() { return -1; }
                    @Override
                    public int getSatOff() { return -1; }
                    @Override
                    public int getSatMod() { return -1; }
                    @Override
                    public int getLumOff() { return -1; }
                    @Override
                    public int getLumMod() { return -1; }
                    @Override
                    public int getShade() { return -1; }
                    @Override
                    public int getTint() { return -1; }


                };
        }

        SimpleSolidPaint(ColorStyle color) {
            if (color == null) {
                throw new NullPointerException("Color needs to be specified");
            }
            this.solidColor = color;
        }

        @Override
        public ColorStyle getSolidColor() {
            return solidColor;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (!(o instanceof SolidPaint)) {
                return false;
            }
            return Objects.equals(getSolidColor(), ((SolidPaint) o).getSolidColor());
        }

        @Override
        public int hashCode() {
            return Objects.hash(solidColor);
        }
    }

    public static SolidPaint createSolidPaint(final Color color) {
        return (color == null) ? null : new SimpleSolidPaint(color);
    }

    public static SolidPaint createSolidPaint(final ColorStyle color) {
        return (color == null) ? null : new SimpleSolidPaint(color);
    }

    public Paint getPaint(Graphics2D graphics, PaintStyle paint) {
        return getPaint(graphics, paint, PaintModifier.NORM);
    }

    public Paint getPaint(Graphics2D graphics, PaintStyle paint, PaintModifier modifier) {
        if (modifier == PaintModifier.NONE) {
            return null;
        }
        if (paint instanceof SolidPaint) {
            return getSolidPaint((SolidPaint)paint, graphics, modifier);
        } else if (paint instanceof GradientPaint) {
            return getGradientPaint((GradientPaint)paint, graphics);
        } else if (paint instanceof TexturePaint) {
            return getTexturePaint((TexturePaint)paint, graphics);
        }
        return null;
    }

    @SuppressWarnings({"WeakerAccess", "unused"})
    protected Paint getSolidPaint(SolidPaint fill, Graphics2D graphics, final PaintModifier modifier) {
        final ColorStyle orig = fill.getSolidColor();
        ColorStyle cs = new AbstractColorStyle() {
            @Override
            public Color getColor() {
                return orig.getColor();
            }

            @Override
            public int getAlpha() {
                return orig.getAlpha();
            }

            @Override
            public int getHueOff() {
                return orig.getHueOff();
            }

            @Override
            public int getHueMod() {
                return orig.getHueMod();
            }

            @Override
            public int getSatOff() {
                return orig.getSatOff();
            }

            @Override
            public int getSatMod() {
                return orig.getSatMod();
            }

            @Override
            public int getLumOff() {
                return orig.getLumOff();
            }

            @Override
            public int getLumMod() {
                return orig.getLumMod();
            }

            @Override
            public int getShade() {
                return scale(orig.getShade(), PaintModifier.DARKEN_LESS, PaintModifier.DARKEN);
            }

            @Override
            public int getTint() {
                return scale(orig.getTint(), PaintModifier.LIGHTEN_LESS, PaintModifier.LIGHTEN);
            }

            private int scale(int value, PaintModifier lessModifier, PaintModifier moreModifier) {
                int delta = (modifier == lessModifier ? 20000 : (modifier == moreModifier ? 40000 : 0));
                return Math.min(100000, Math.max(0,value)+delta);
            }
        };

        return applyColorTransform(cs);
    }

    @SuppressWarnings("WeakerAccess")
    protected Paint getGradientPaint(GradientPaint fill, Graphics2D graphics) {
        switch (fill.getGradientType()) {
        case linear:
            return createLinearGradientPaint(fill, graphics);
        case circular:
            return createRadialGradientPaint(fill, graphics);
        case shape:
            return createPathGradientPaint(fill, graphics);
        default:
            throw new UnsupportedOperationException("gradient fill of type "+fill+" not supported.");
        }
    }

    @SuppressWarnings("WeakerAccess")
    protected Paint getTexturePaint(TexturePaint fill, Graphics2D graphics) {
        InputStream is = fill.getImageData();
        if (is == null) {
            return null;
        }
        assert(graphics != null);

        ImageRenderer renderer = DrawPictureShape.getImageRenderer(graphics, fill.getContentType());

        try {
            try {
                renderer.loadImage(is, fill.getContentType());
            } finally {
                is.close();
            }
        } catch (IOException e) {
            LOG.log(POILogger.ERROR, "Can't load image data - using transparent color", e);
            return null;
        }

        int alpha = fill.getAlpha();
        if (0 <= alpha && alpha < 100000) {
            renderer.setAlpha(alpha/100000.f);
        }

        Rectangle2D textAnchor = shape.getAnchor();
        BufferedImage image;
        if ("image/x-wmf".equals(fill.getContentType())) {
            // don't rely on wmf dimensions, use dimension of anchor
            // TODO: check pixels vs. points for image dimension
            image = renderer.getImage(new Dimension((int)textAnchor.getWidth(), (int)textAnchor.getHeight()));
        } else {
            image = renderer.getImage();
        }

        if(image == null) {
            LOG.log(POILogger.ERROR, "Can't load image data");
            return null;
        }

        return new java.awt.TexturePaint(image, textAnchor);
    }

    /**
     * Convert color transformations in {@link ColorStyle} to a {@link Color} instance
     *
     * @see <a href="https://msdn.microsoft.com/en-us/library/dd560821%28v=office.12%29.aspx">Using Office Open XML to Customize Document Formatting in the 2007 Office System</a>
     * @see <a href="https://social.msdn.microsoft.com/Forums/office/en-US/040e0a1f-dbfe-4ce5-826b-38b4b6f6d3f7/saturation-modulation-satmod">saturation modulation (satMod)</a>
     * @see <a href="http://stackoverflow.com/questions/6754127/office-open-xml-satmod-results-in-more-than-100-saturation">Office Open XML satMod results in more than 100% saturation</a>
     */
    public static Color applyColorTransform(ColorStyle color){
        // TODO: The colors don't match 100% the results of Powerpoint, maybe because we still
        // operate in sRGB and not scRGB ... work in progress ...
        if (color == null || color.getColor() == null) {
            return TRANSPARENT;
        }

        Color result = color.getColor();

        double alpha = getAlpha(result, color);
        double[] hsl = RGB2HSL(result); // values are in the range [0..100] (usually ...)
        applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff());
        applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff());
        applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff());
        applyShade(hsl, color);
        applyTint(hsl, color);

        result = HSL2RGB(hsl[0], hsl[1], hsl[2], alpha);

        return result;
    }

    private static double getAlpha(Color c, ColorStyle fc) {
        double alpha = c.getAlpha()/255d;
        int fcAlpha = fc.getAlpha();
        if (fcAlpha != -1) {
            alpha *= fcAlpha/100000d;
        }
        return Math.min(1, Math.max(0, alpha));
    }

    /**
     * Apply the modulation and offset adjustments to the given HSL part
     *
     * Example for lumMod/lumOff:
     * The lumMod value is the percent luminance. A lumMod value of "60000",
     * is 60% of the luminance of the original color.
     * When the color is a shade of the original theme color, the lumMod
     * attribute is the only one of the tags shown here that appears.
     * The <a:lumOff> tag appears after the <a:lumMod> tag when the color is a
     * tint of the original. The lumOff value always equals 1-lumMod, which is used in the tint calculation
     *
     * Despite having different ways to display the tint and shade percentages,
     * all of the programs use the same method to calculate the resulting color.
     * Convert the original RGB value to HSL ... and then adjust the luminance (L)
     * with one of the following equations before converting the HSL value back to RGB.
     * (The % tint in the following equations refers to the tint, themetint, themeshade,
     * or lumMod values, as applicable.)
     *
     * @param hsl the hsl values
     * @param hslPart the hsl part to modify [0..2]
     * @param mod the modulation adjustment
     * @param off the offset adjustment
     */
    private static void applyHslModOff(double[] hsl, int hslPart, int mod, int off) {
        if (mod == -1) {
            mod = 100000;
        }
        if (off == -1) {
            off = 0;
        }
        if (!(mod == 100000 && off == 0)) {
            double fOff = off / 1000d;
            double fMod = mod / 100000d;
            hsl[hslPart] = hsl[hslPart]*fMod+fOff;
        }
    }

    /**
     * Apply the shade
     *
     * For a shade, the equation is luminance * %tint.
     */
    private static void applyShade(double[] hsl, ColorStyle fc) {
        int shade = fc.getShade();
        if (shade == -1) {
            return;
        }

        double shadePct = shade / 100000.;

        hsl[2] *= 1. - shadePct;
    }

    /**
     * Apply the tint
     *
     * For a tint, the equation is luminance * %tint + (1-%tint).
     * (Note that 1-%tint is equal to the lumOff value in DrawingML.)
     */
    private static void applyTint(double[] hsl, ColorStyle fc) {
        int tint = fc.getTint();
        if (tint == -1) {
            return;
        }

        // see 18.8.19 fgColor (Foreground Color)
        double tintPct = tint / 100000.;
        hsl[2] = hsl[2]*(1.-tintPct) + (100.-100.*(1.-tintPct));
    }

    @SuppressWarnings("WeakerAccess")
    protected Paint createLinearGradientPaint(GradientPaint fill, Graphics2D graphics) {
        // TODO: we need to find the two points for gradient - the problem is, which point at the outline
        // do you take? My solution would be to apply the gradient rotation to the shape in reverse
        // and then scan the shape for the largest possible horizontal distance

        double angle = fill.getGradientAngle();
        if (!fill.isRotatedWithShape()) {
            angle -= shape.getRotation();
        }

        Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);

        AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(angle), anchor.getCenterX(), anchor.getCenterY());

        double diagonal = Math.sqrt(Math.pow(anchor.getWidth(),2) + Math.pow(anchor.getHeight(),2));
        final Point2D p1 = at.transform(new Point2D.Double(anchor.getCenterX() - diagonal / 2, anchor.getCenterY()), null);
        final Point2D p2 = at.transform(new Point2D.Double(anchor.getMaxX(), anchor.getCenterY()), null);

//        snapToAnchor(p1, anchor);
//        snapToAnchor(p2, anchor);

        // gradient paint on the same point throws an exception ... and doesn't make sense
        return (p1.equals(p2)) ? null : safeFractions((f,c)->new LinearGradientPaint(p1,p2,f,c), fill);
    }


    @SuppressWarnings("WeakerAccess")
    protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) {
        Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);

        final Point2D pCenter = new Point2D.Double(anchor.getCenterX(), anchor.getCenterY());

        final float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight());

        return safeFractions((f,c)->new RadialGradientPaint(pCenter,radius,f,c), fill);
    }

    @SuppressWarnings({"WeakerAccess", "unused"})
    protected Paint createPathGradientPaint(GradientPaint fill, Graphics2D graphics) {
        // currently we ignore an eventually center setting

        return safeFractions(PathGradientPaint::new, fill);
    }

    private Paint safeFractions(BiFunction<float[],Color[],Paint> init, GradientPaint fill) {
        float[] fractions = fill.getGradientFractions();
        final ColorStyle[] styles = fill.getGradientColors();

        // need to remap the fractions, because Java doesn't like repeating fraction values
        Map<Float,Color> m = new TreeMap<>();
        for (int i = 0; i<fractions.length; i++) {
            // if fc is null, use transparent color to get color of background
            m.put(fractions[i], (styles[i] == null ? TRANSPARENT : applyColorTransform(styles[i])));
        }

        final Color[] colors = new Color[m.size()];
        if (fractions.length != m.size()) {
            fractions = new float[m.size()];
        }

        int i=0;
        for (Map.Entry<Float,Color> me : m.entrySet()) {
            fractions[i] = me.getKey();
            colors[i] = me.getValue();
            i++;
        }

        return init.apply(fractions, colors);
    }

    /**
     *  Convert HSL values to a RGB Color.
     *
     *  @param h Hue is specified as degrees in the range 0 - 360.
     *  @param s Saturation is specified as a percentage in the range 1 - 100.
     *  @param l Luminance is specified as a percentage in the range 1 - 100.
     *  @param alpha  the alpha value between 0 - 1
     *
     *  @return the RGB Color object
     */
    public static Color HSL2RGB(double h, double s, double l, double alpha) {
        // we clamp the values, as it possible to come up with more than 100% sat/lum
        // (see links in applyColorTransform() for more info)
        s = Math.max(0, Math.min(100, s));
        l = Math.max(0, Math.min(100, l));

        if (alpha <0.0f || alpha > 1.0f) {
            String message = "Color parameter outside of expected range - Alpha: " + alpha;
            throw new IllegalArgumentException( message );
        }

        //  Formula needs all values between 0 - 1.

        h = h % 360.0f;
        h /= 360f;
        s /= 100f;
        l /= 100f;

        double q = (l < 0.5d)
            ? l * (1d + s)
            : (l + s) - (s * l);

        double p = 2d * l - q;

        double r = Math.max(0, HUE2RGB(p, q, h + (1.0d / 3.0d)));
        double g = Math.max(0, HUE2RGB(p, q, h));
        double b = Math.max(0, HUE2RGB(p, q, h - (1.0d / 3.0d)));

        r = Math.min(r, 1.0d);
        g = Math.min(g, 1.0d);
        b = Math.min(b, 1.0d);

        return new Color((float)r, (float)g, (float)b, (float)alpha);
    }

    private static double HUE2RGB(double p, double q, double h) {
        if (h < 0d) {
            h += 1d;
        }

        if (h > 1d) {
            h -= 1d;
        }

        if (6d * h < 1d) {
            return p + ((q - p) * 6d * h);
        }

        if (2d * h < 1d) {
            return q;
        }

        if (3d * h < 2d) {
            return p + ( (q - p) * 6d * ((2.0d / 3.0d) - h) );
        }

        return p;
    }


    /**
     *  Convert a RGB Color to it corresponding HSL values.
     *
     *  @return an array containing the 3 HSL values.
     */
    private static double[] RGB2HSL(Color color)
    {
        //  Get RGB values in the range 0 - 1

        float[] rgb = color.getRGBColorComponents( null );
        double r = rgb[0];
        double g = rgb[1];
        double b = rgb[2];

        //  Minimum and Maximum RGB values are used in the HSL calculations

        double min = Math.min(r, Math.min(g, b));
        double max = Math.max(r, Math.max(g, b));

        //  Calculate the Hue

        double h = 0;

        if (max == min) {
            h = 0;
        } else if (max == r) {
            h = ((60d * (g - b) / (max - min)) + 360d) % 360d;
        } else if (max == g) {
            h = (60d * (b - r) / (max - min)) + 120d;
        } else if (max == b) {
            h = (60d * (r - g) / (max - min)) + 240d;
        }

        //  Calculate the Luminance

        double l = (max + min) / 2d;

        //  Calculate the Saturation

        final double s;

        if (max == min) {
            s = 0;
        } else if (l <= .5d) {
            s = (max - min) / (max + min);
        } else {
            s = (max - min) / (2d - max - min);
        }

        return new double[] {h, s * 100, l * 100};
    }

    /**
     * Convert sRGB float component [0..1] from sRGB to linear RGB [0..100000]
     *
     * @see Color#getRGBColorComponents(float[])
     */
    public static int srgb2lin(float sRGB) {
        // scRGB has a linear gamma of 1.0, scale the AWT-Color which is in sRGB to linear RGB
        // see https://en.wikipedia.org/wiki/SRGB (the reverse transformation)
        if (sRGB <= 0.04045d) {
            return (int)Math.rint(100000d * sRGB / 12.92d);
        } else {
            return (int)Math.rint(100000d * Math.pow((sRGB + 0.055d) / 1.055d, 2.4d));
        }
    }

    /**
     * Convert linear RGB [0..100000] to sRGB float component [0..1]
     *
     * @see Color#getRGBColorComponents(float[])
     */
    public static float lin2srgb(int linRGB) {
        // color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color
        // see https://en.wikipedia.org/wiki/SRGB (The forward transformation)
        if (linRGB <= 0.0031308d) {
            return (float)(linRGB / 100000d * 12.92d);
        } else {
            return (float)(1.055d * Math.pow(linRGB / 100000d, 1.0d/2.4d) - 0.055d);
        }
    }
}
