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

import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherArrayProperty;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherColorRef;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherPropertyTypes;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherRecordTypes;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.hslf.record.Document;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.ColorStyle;
import org.apache.poi.sl.usermodel.FillStyle;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint.GradientType;
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.Units;

import static org.apache.logging.log4j.util.Unbox.box;

/**
 * Represents functionality provided by the 'Fill Effects' dialog in PowerPoint.
 */
@SuppressWarnings("WeakerAccess")
public final class HSLFFill {
    private static final Logger LOG = LogManager.getLogger(HSLFFill.class);

    /**
     *  Fill with a solid color
     */
    static final int FILL_SOLID = 0;

    /**
     *  Fill with a pattern (bitmap)
     */
    static final int FILL_PATTERN = 1;

    /**
     *  A texture (pattern with its own color map)
     */
    static final int FILL_TEXTURE = 2;

    /**
     *  Center a picture in the shape
     */
    static final int FILL_PICTURE = 3;

    /**
     *  Shade from start to end points
     */
    static final int FILL_SHADE = 4;

    /**
     *  Shade from bounding rectangle to end point
     */
    static final int FILL_SHADE_CENTER = 5;

    /**
     *  Shade from shape outline to end point
     */
    static final int FILL_SHADE_SHAPE = 6;

    /**
     *  Similar to FILL_SHADE, but the fill angle
     *  is additionally scaled by the aspect ratio of
     *  the shape. If shape is square, it is the same as FILL_SHADE
     */
    static final int FILL_SHADE_SCALE = 7;

    /**
     *  shade to title
     */
    static final int FILL_SHADE_TITLE = 8;

    /**
     *  Use the background fill color/pattern
     */
    static final int FILL_BACKGROUND = 9;

    /**
     * A bit that specifies whether the RecolorFillAsPicture bit is set.
     * A value of 0x0 specifies that the fRecolorFillAsPicture MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_USE_RECOLOR_FILL_AS_PICTURE = BitFieldFactory.getInstance(0x00400000);

    /**
     * A bit that specifies whether the UseShapeAnchor bit is set.
     * A value of 0x0 specifies that the fUseShapeAnchor MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_USE_USE_SHAPE_ANCHOR = BitFieldFactory.getInstance(0x00200000);

    /**
     * A bit that specifies whether the Filled bit is set.
     * A value of 0x0 specifies that the Filled MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_USE_FILLED = BitFieldFactory.getInstance(0x00100000);

    /**
     * A bit that specifies whether the HitTestFill bit is set.
     * A value of 0x0 specifies that the HitTestFill MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_USE_HIT_TEST_FILL = BitFieldFactory.getInstance(0x00080000);
    
    /**
     * A bit that specifies whether the fillShape bit is set.
     * A value of 0x0 specifies that the fillShape MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_USE_FILL_SHAPE = BitFieldFactory.getInstance(0x00040000);
    
    /**
     * A bit that specifies whether the fillUseRect bit is set.
     * A value of 0x0 specifies that the fillUseRect MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_USE_FILL_USE_RECT = BitFieldFactory.getInstance(0x00020000);
    
    /**
     * A bit that specifies whether the fNoFillHitTest bit is set.
     * A value of 0x0 specifies that the fNoFillHitTest MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_USE_NO_FILL_HIT_TEST = BitFieldFactory.getInstance(0x00010000);
    
    /**
     * A bit that specifies how to recolor a picture fill. If this bit is set to 0x1, the pictureFillCrMod
     * property of the picture fill is used for recoloring. If this bit is set to 0x0, the fillCrMod property,
     * as defined in section 2.3.7.6, is used for recoloring.
     * If UsefRecolorFillAsPicture equals 0x0, this value MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_RECOLOR_FILL_AS_PICTURE = BitFieldFactory.getInstance(0x00000040);
    
    /**
     * A bit that specifies whether the fill is rotated with the shape.
     * If UseUseShapeAnchor equals 0x0, this value MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_USE_SHAPE_ANCHOR = BitFieldFactory.getInstance(0x00000020);
    
    /**
     * A bit that specifies whether the fill is rendered if the shape is a 2-D shape.
     * If this bit is set to 0x1, the fill of this shape is rendered based on the properties of the Fill Style
     * property set. If this bit is set to 0x0, the fill of this shape is not rendered.
     * If UseFilled is 0x0, this value MUST be ignored. The default value for this property is 0x1.
     */
    private static final BitField FILL_FILLED = BitFieldFactory.getInstance(0x00000010);
    
    /**
     * A bit that specifies whether this fill will be hit tested.
     * If UsefHitTestFill equals 0x0, this value MUST be ignored.
     * The default value for this property is 0x1.
     */
    private static final BitField FILL_HIT_TEST_FILL = BitFieldFactory.getInstance(0x00000008);
    
    /**
     * A bit that specifies how the fill is aligned. If this bit is set to 0x1, the fill is
     * aligned relative to the shape so that it moves with the shape. If this bit is set to 0x0,
     * the fill is aligned with the origin of the view. If fUsefillShape equals 0x0, this value MUST be ignored.
     * The default value for this property is 0x1.
     */
    private static final BitField FILL_FILL_SHAPE = BitFieldFactory.getInstance(0x00000004);
    
    /**
     * A bit that specifies whether to use the rectangle specified by the fillRectLeft, fillRectRight,
     * fillRectTop, and fillRectBottom properties, rather than the bounding rectangle of the shape,
     * as the filled area. If fUsefillUseRect equals 0x0, this value MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_FILL_USE_RECT = BitFieldFactory.getInstance(0x00000002);
    
    /**
     * A bit that specifies whether this shape will be hit tested as though it were filled.
     * If UsefNoFillHitTest equals 0x0, this value MUST be ignored.
     * The default value for this property is 0x0.
     */
    private static final BitField FILL_NO_FILL_HIT_TEST = BitFieldFactory.getInstance(0x00000001);


    /**
     * The shape this background applies to
     */
    private HSLFShape shape;

    /**
     * Construct a {@code Fill} object for a shape.
     * Fill information will be read from shape's escher properties.
     *
     * @param shape the shape this background applies to
     */
    public HSLFFill(HSLFShape shape){
        this.shape = shape;
    }


    public FillStyle getFillStyle() {
        return this::getPaintStyle;
    }

    private PaintStyle getPaintStyle() {
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();

        EscherSimpleProperty hitProp = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST);
        int propVal = (hitProp == null) ? 0 : hitProp.getPropertyValue();

        EscherSimpleProperty masterProp = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.SHAPE__MASTER);

        if (!FILL_USE_FILLED.isSet(propVal) && masterProp != null) {
            int masterId = masterProp.getPropertyValue();
            HSLFShape o = shape.getSheet().getMasterSheet().getShapes().stream().filter(s -> s.getShapeId() == masterId).findFirst().orElse(null);
            return o != null ? o.getFillStyle().getPaint() : null;
        }

        final int fillType = getFillType();
        // TODO: fix gradient types, this mismatches with the MS-ODRAW definition ...
        // need to handle (not only) the type (radial,rectangular,linear),
        // the direction, e.g. top right, and bounds (e.g. for rectangular boxes)
        switch (fillType) {
            case FILL_SOLID:
                return DrawPaint.createSolidPaint(getForegroundColor());
            case FILL_SHADE_SHAPE:
                return getGradientPaint(GradientType.shape);
            case FILL_SHADE_CENTER:
            case FILL_SHADE_TITLE:
                return getGradientPaint(GradientType.circular);
            case FILL_SHADE:
            case FILL_SHADE_SCALE:
                return getGradientPaint(GradientType.linear);
            case FILL_PICTURE:
                return getTexturePaint();
            default:
                LOG.atWarn().log("unsupported fill type: {}", box(fillType));
                return null;
        }
    }
    
    private boolean isRotatedWithShape() {
        // NOFILLHITTEST can be in the normal escher opt record but also in the tertiary record
        // the extended bit fields seem to be in the second
        AbstractEscherOptRecord opt = shape.getEscherChild(EscherRecordTypes.USER_DEFINED);
        EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST);
        int propVal = (p == null) ? 0 : p.getPropertyValue();
        return FILL_USE_USE_SHAPE_ANCHOR.isSet(propVal) && FILL_USE_SHAPE_ANCHOR.isSet(propVal);
    }

    private GradientPaint getGradientPaint(final GradientType gradientType) {
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();

        EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST);
        int propVal = (p == null) ? 0 : p.getPropertyValue();

        if (FILL_USE_FILLED.isSet(propVal) && !FILL_FILLED.isSet(propVal)) {
            return null;
        }


        final EscherArrayProperty ep = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__SHADECOLORS);
        final int colorCnt = (ep == null) ? 0 : ep.getNumberOfElementsInArray();

        final List<Color> colors = new ArrayList<>();
        final List<Float> fractions = new ArrayList<>();

        // TODO: handle palette colors and alpha(?) value
        if (colorCnt == 0) {
            colors.add(getBackgroundColor());
            colors.add(getForegroundColor());
            fractions.add(0f);
            fractions.add(1f);
        } else {
            ep.forEach(data -> {
                EscherColorRef ecr = new EscherColorRef(data, 0, 4);
                colors.add(shape.getColor(ecr));
                double pos = Units.fixedPointToDouble(LittleEndian.getInt(data, 4));
                fractions.add((float)pos);
            });
        }

        int focus = getFillFocus();
        if (focus == 100 || focus == -100) {
            Collections.reverse(colors);
        } else if (focus != 0) {
            if (focus < 0) {
                focus = 100+focus;
            }
            // TODO: depending on fill focus, rotation with shape and other escher properties
            // there are still a lot of cases where we get the gradients wrong
            List<Color> reflectedColors = new ArrayList<>(colors.subList(1,colors.size()));
            Collections.reverse(reflectedColors);
            colors.addAll(0, reflectedColors);

            final List<Float> fractRev = new ArrayList<>();
            for (int i=fractions.size()-2; i >= 0; i--) {
                float val = (float)(1 - fractions.get(i) * focus / 100.);
                fractRev.add(val);
            }
            for (int i=0; i<fractions.size(); i++) {
                float val = (float)(fractions.get(i) * focus / 100.);
                fractions.set(i, val);
            }
            fractions.addAll(fractRev);
        }

        return new GradientPaint() {
            @Override
            public double getGradientAngle() {
                // A value of type FixedPoint, as specified in [MS-OSHARED] section 2.2.1.6,
                // that specifies the angle of the gradient fill. Zero degrees represents a vertical vector from
                // bottom to top. The default value for this property is 0x00000000.
                int rot = shape.getEscherProperty(EscherPropertyTypes.FILL__ANGLE);
                return 90-Units.fixedPointToDouble(rot);
            }

            @Override
            public ColorStyle[] getGradientColors() {
                return colors.stream().map(this::wrapColor).toArray(ColorStyle[]::new);
            }
            
            private ColorStyle wrapColor(Color col) {
                return (col == null) ? null : DrawPaint.createSolidPaint(col).getSolidColor();
            }
            
            @Override
            public float[] getGradientFractions() {
                float[] frc = new float[fractions.size()];
                for (int i = 0; i<fractions.size(); i++) {
                    frc[i] = fractions.get(i);
                }
                return frc;
            }
            
            @Override
            public boolean isRotatedWithShape() {
                return HSLFFill.this.isRotatedWithShape();
            }
            
            @Override
            public GradientType getGradientType() {
                return gradientType;
            }
        };
    }
    
    private TexturePaint getTexturePaint() {
        final HSLFPictureData pd = getPictureData();
        if (pd == null) {
            return null;
        }

        return new TexturePaint() {
            @Override
            public InputStream getImageData() {
                return new ByteArrayInputStream(pd.getData());
            }

            @Override
            public String getContentType() {
                return pd.getContentType();
            }

            @Override
            public int getAlpha() {
                return (int)(shape.getAlpha(EscherPropertyTypes.FILL__FILLOPACITY)*100000.0);
            }

            @Override
            public boolean isRotatedWithShape() {
                return HSLFFill.this.isRotatedWithShape();
            }
        };
    }

    /**
     * Returns fill type.
     * Must be one of the {@code FILL_*} constants defined in this class.
     *
     * @return type of fill
     */
    public int getFillType(){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        EscherSimpleProperty prop = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__FILLTYPE);
        return prop == null ? FILL_SOLID : prop.getPropertyValue();
    }

    /**
     * The fillFocus property specifies the relative position of the last color in the shaded fill.
     * Its used to specify the center of an reflected fill. 0 = no reflection, 50 = reflected in the middle.
     * If fillFocus is less than 0, the relative position of the last color is outside the shape,
     * and the relative position of the first color is within the shape.
     *
     * @return a percentage in the range of -100 .. 100; defaults to 0
     */
    public int getFillFocus() {
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        EscherSimpleProperty prop = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__FOCUS);
        return prop == null ? 0 : prop.getPropertyValue();
    }

    void afterInsert(HSLFSheet sh){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__PATTERNTEXTURE);
        if(p != null) {
            int idx = p.getPropertyValue();
            EscherBSERecord bse = getEscherBSERecord(idx);
            if (bse != null) {
                bse.setRef(bse.getRef() + 1);
            }
        }
    }

    @SuppressWarnings("resource")
    EscherBSERecord getEscherBSERecord(int idx){
        HSLFSheet sheet = shape.getSheet();
        if(sheet == null) {
            LOG.atDebug().log("Fill has not yet been assigned to a sheet");
            return null;
        }
        HSLFSlideShow ppt = sheet.getSlideShow();
        Document doc = ppt.getDocumentRecord();
        EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
        EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
        if(bstore == null) {
            LOG.atDebug().log("EscherContainerRecord.BSTORE_CONTAINER was not found ");
            return null;
        }
        return (EscherBSERecord) bstore.getChild(idx-1);
    }

    /**
     * Sets fill type.
     * Must be one of the {@code FILL_*} constants defined in this class.
     *
     * @param type type of the fill
     */
    public void setFillType(int type){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        HSLFShape.setEscherProperty(opt, EscherPropertyTypes.FILL__FILLTYPE, type);
    }

    /**
     * Foreground color
     */
    public Color getForegroundColor(){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST);
        int propVal = (p == null) ? 0 : p.getPropertyValue();

        return (!FILL_USE_FILLED.isSet(propVal) || (FILL_USE_FILLED.isSet(propVal) && FILL_FILLED.isSet(propVal)))
            ? shape.getColor(EscherPropertyTypes.FILL__FILLCOLOR, EscherPropertyTypes.FILL__FILLOPACITY)
            : null;
    }

    /**
     * Foreground color
     */
    public void setForegroundColor(Color color){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        opt.removeEscherProperty(EscherPropertyTypes.FILL__FILLOPACITY);
        opt.removeEscherProperty(EscherPropertyTypes.FILL__FILLCOLOR);

        if (color != null) {
            int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
            HSLFShape.setEscherProperty(opt, EscherPropertyTypes.FILL__FILLCOLOR, rgb);
            int alpha = color.getAlpha();
            if (alpha < 255) {
                int alphaFP = Units.doubleToFixedPoint(alpha/255d);
                HSLFShape.setEscherProperty(opt, EscherPropertyTypes.FILL__FILLOPACITY, alphaFP);
            }
        }
        
        EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST);
        int propVal = (p == null) ? 0 : p.getPropertyValue();
        propVal = FILL_FILLED.setBoolean(propVal, color != null);
        propVal = FILL_NO_FILL_HIT_TEST.setBoolean(propVal, color != null);
        propVal = FILL_USE_FILLED.set(propVal);
        propVal = FILL_USE_FILL_SHAPE.set(propVal);
        propVal = FILL_USE_NO_FILL_HIT_TEST.set(propVal);
        // TODO: check why we always clear this ...
        propVal = FILL_FILL_SHAPE.clear(propVal);

        HSLFShape.setEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST, propVal);
    }

    /**
     * Background color
     */
    public Color getBackgroundColor(){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST);
        int propVal = (p == null) ? 0 : p.getPropertyValue();

        return (!FILL_USE_FILLED.isSet(propVal) || (FILL_USE_FILLED.isSet(propVal) && FILL_FILLED.isSet(propVal)))
            ? shape.getColor(EscherPropertyTypes.FILL__FILLBACKCOLOR, EscherPropertyTypes.FILL__FILLOPACITY)
            : null;
    }

    /**
     * Background color
     */
    public void setBackgroundColor(Color color){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        if (color == null) {
            HSLFShape.setEscherProperty(opt, EscherPropertyTypes.FILL__FILLBACKCOLOR, -1);
        }
        else {
            int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
            HSLFShape.setEscherProperty(opt, EscherPropertyTypes.FILL__FILLBACKCOLOR, rgb);
        }
    }

    /**
     * {@code PictureData} object used in a texture, pattern of picture fill.
     */
    @SuppressWarnings("resource")
    public HSLFPictureData getPictureData(){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__PATTERNTEXTURE);
        if (p == null) {
            return null;
        }

        HSLFSlideShow ppt = shape.getSheet().getSlideShow();
        List<HSLFPictureData> pict = ppt.getPictureData();
        Document doc = ppt.getDocumentRecord();

        EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
        EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);

        int idx = p.getPropertyValue();
        if (idx == 0){
            LOG.atWarn().log("no reference to picture data found ");
        } else {
            EscherBSERecord bse = (EscherBSERecord) bstore.getChild(idx - 1);
            for (HSLFPictureData pd : pict) {

                // Reference equals is safe because these BSE belong to the same slideshow
                if (pd.bse == bse) {
                    return pd;
                }
            }
        }

        return null;
    }

    /**
     * Assign picture used to fill the underlying shape.
     *
     * @param data the picture data added to this ppt by {@link HSLFSlideShow#addPicture(byte[], PictureData.PictureType)} method.
     */
    public void setPictureData(HSLFPictureData data){
        AbstractEscherOptRecord opt = shape.getEscherOptRecord();
        HSLFShape.setEscherProperty(opt, EscherPropertyTypes.FILL__PATTERNTEXTURE, true, (data == null ? 0 : data.getIndex()));
        if(data != null && shape.getSheet() != null) {
            EscherBSERecord bse = getEscherBSERecord(data.getIndex());
            if (bse != null) {
                bse.setRef(bse.getRef() + 1);
            }
        }
    }

}
