/* ====================================================================
   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 static org.apache.poi.hslf.usermodel.HSLFFreeformShape.ShapePath.CURVES_CLOSED;
import static org.apache.poi.hslf.usermodel.HSLFFreeformShape.ShapePath.LINES_CLOSED;

import java.awt.geom.Arc2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;

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.EscherContainerRecord;
import org.apache.poi.ddf.EscherPropertyTypes;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.sl.draw.geom.AdjustPoint;
import org.apache.poi.sl.draw.geom.ArcToCommand;
import org.apache.poi.sl.draw.geom.ClosePathCommand;
import org.apache.poi.sl.draw.geom.CurveToCommand;
import org.apache.poi.sl.draw.geom.CustomGeometry;
import org.apache.poi.sl.draw.geom.LineToCommand;
import org.apache.poi.sl.draw.geom.MoveToCommand;
import org.apache.poi.sl.draw.geom.Path;
import org.apache.poi.sl.usermodel.AutoShape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.ShapeTypes;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;

/**
 * Represents an AutoShape.<p>
 *
 * AutoShapes are drawing objects with a particular shape that may be customized through smart resizing and adjustments.
 * See {@link ShapeTypes}
 */
public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape,HSLFTextParagraph> {
    private static final Logger LOG = LogManager.getLogger(HSLFAutoShape.class);

    static final byte[] SEGMENTINFO_MOVETO   = new byte[]{0x00, 0x40};
    static final byte[] SEGMENTINFO_LINETO   = new byte[]{0x00, (byte)0xAC};
    static final byte[] SEGMENTINFO_ESCAPE   = new byte[]{0x01, 0x00};
    static final byte[] SEGMENTINFO_ESCAPE2  = new byte[]{0x01, 0x20};
    static final byte[] SEGMENTINFO_CUBICTO  = new byte[]{0x00, (byte)0xAD};
    // OpenOffice inserts 0xB3 instead of 0xAD.
    // protected static final byte[] SEGMENTINFO_CUBICTO2 = new byte[]{0x00, (byte)0xB3};
    static final byte[] SEGMENTINFO_CLOSE    = new byte[]{0x01, (byte)0x60};
    static final byte[] SEGMENTINFO_END      = new byte[]{0x00, (byte)0x80};

    private static final BitField PATH_INFO = BitFieldFactory.getInstance(0xE000);
    private static final BitField ESCAPE_INFO = BitFieldFactory.getInstance(0x1F00);

    enum PathInfo {
        lineTo(0),curveTo(1),moveTo(2),close(3),end(4),escape(5),clientEscape(6);
        private final int flag;
        PathInfo(int flag) {
            this.flag = flag;
        }
        public int getFlag() {
            return flag;
        }
        static PathInfo valueOf(int flag) {
            for (PathInfo v : values()) {
                if (v.flag == flag) {
                    return v;
                }
            }
            return null;
        }
    }

    enum EscapeInfo {
        EXTENSION(0x0000),
        ANGLE_ELLIPSE_TO(0x0001),
        ANGLE_ELLIPSE(0x0002),
        ARC_TO(0x0003),
        ARC(0x0004),
        CLOCKWISE_ARC_TO(0x0005),
        CLOCKWISE_ARC(0x0006),
        ELLIPTICAL_QUADRANT_X(0x0007),
        ELLIPTICAL_QUADRANT_Y(0x0008),
        QUADRATIC_BEZIER(0x0009),
        NO_FILL(0X000A),
        NO_LINE(0X000B),
        AUTO_LINE(0X000C),
        AUTO_CURVE(0X000D),
        CORNER_LINE(0X000E),
        CORNER_CURVE(0X000F),
        SMOOTH_LINE(0X0010),
        SMOOTH_CURVE(0X0011),
        SYMMETRIC_LINE(0X0012),
        SYMMETRIC_CURVE(0X0013),
        FREEFORM(0X0014),
        FILL_COLOR(0X0015),
        LINE_COLOR(0X0016);

        private final int flag;
        EscapeInfo(int flag) {
            this.flag = flag;
        }
        public int getFlag() {
            return flag;
        }
        static EscapeInfo valueOf(int flag) {
            for (EscapeInfo v : values()) {
                if (v.flag == flag) {
                    return v;
                }
            }
            return null;
        }
    }

    protected HSLFAutoShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
        super(escherRecord, parent);
    }

    public HSLFAutoShape(ShapeType type, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
        super(null, parent);
        createSpContainer(type, parent instanceof HSLFGroupShape);
    }

    public HSLFAutoShape(ShapeType type){
        this(type, null);
    }

    protected EscherContainerRecord createSpContainer(ShapeType shapeType, boolean isChild){
        EscherContainerRecord ecr = super.createSpContainer(isChild);

        setShapeType(shapeType);

        //set default properties for an autoshape
        setEscherProperty(EscherPropertyTypes.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
        setEscherProperty(EscherPropertyTypes.FILL__FILLCOLOR, 0x8000004);
        setEscherProperty(EscherPropertyTypes.FILL__FILLCOLOR, 0x8000004);
        setEscherProperty(EscherPropertyTypes.FILL__FILLBACKCOLOR, 0x8000000);
        setEscherProperty(EscherPropertyTypes.FILL__NOFILLHITTEST, 0x100010);
        setEscherProperty(EscherPropertyTypes.LINESTYLE__COLOR, 0x8000001);
        setEscherProperty(EscherPropertyTypes.LINESTYLE__NOLINEDRAWDASH, 0x80008);
        setEscherProperty(EscherPropertyTypes.SHADOWSTYLE__COLOR, 0x8000002);

        return ecr;
    }

    @Override
    protected void setDefaultTextProperties(HSLFTextParagraph _txtrun){
        setVerticalAlignment(VerticalAlignment.MIDDLE);
        setHorizontalCentered(true);
        setWordWrap(false);
    }

    /**
     * Gets adjust value which controls smart resizing of the auto-shape.<p>
     *
     * The adjustment values are given in shape coordinates:
     * the origin is at the top-left, positive-x is to the right, positive-y is down.
     * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant).
     *
     * @param idx the adjust index in the [0, 9] range
     * @return the adjustment value
     */
    public int getAdjustmentValue(int idx){
        if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range");
        return getEscherProperty(ADJUST_VALUES[idx]);
    }

    /**
     * Sets adjust value which controls smart resizing of the auto-shape.<p>
     *
     * The adjustment values are given in shape coordinates:
     * the origin is at the top-left, positive-x is to the right, positive-y is down.
     * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant).
     *
     * @param idx the adjust index in the [0, 9] range
     * @param val the adjustment value
     */
    public void setAdjustmentValue(int idx, int val){
        if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range");
        setEscherProperty(ADJUST_VALUES[idx], val);
    }

    @Override
    public CustomGeometry getGeometry() {
        return getGeometry(new Path2D.Double());
    }

    CustomGeometry getGeometry(Path2D path2D) {
        final CustomGeometry cusGeo = new CustomGeometry();

        final AbstractEscherOptRecord opt = getEscherOptRecord();

        EscherArrayProperty verticesProp = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__VERTICES);
        EscherArrayProperty segmentsProp = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__SEGMENTINFO);

        // return empty path if either GEOMETRY__VERTICES or GEOMETRY__SEGMENTINFO is missing, see Bugzilla 54188

        //sanity check
        if(verticesProp == null) {
            LOG.atWarn().log("Freeform is missing GEOMETRY__VERTICES ");
            return super.getGeometry();
        }
        if(segmentsProp == null) {
            LOG.atWarn().log("Freeform is missing GEOMETRY__SEGMENTINFO ");
            return super.getGeometry();
        }

        final Iterator<byte[]> vertIter = verticesProp.iterator();
        final Iterator<byte[]> segIter = segmentsProp.iterator();
        final int[] xyPoints = new int[2];
        boolean isClosed = false;

        final Path path = new Path();
        cusGeo.addPath(path);

        while (segIter.hasNext()) {
            byte[] segElem = segIter.next();
            PathInfo pi = getPathInfo(segElem);
            if (pi == null) {
                continue;
            }
            switch (pi) {
                case escape:
                    handleEscapeInfo(path, path2D, segElem, vertIter);
                    break;
                case moveTo:
                    handleMoveTo(vertIter, xyPoints, path, path2D);
                    break;
                case lineTo:
                    handleLineTo(vertIter, xyPoints, path, path2D);
                    break;
                case curveTo:
                    handleCurveTo(vertIter, xyPoints, path, path2D);
                    break;
                case close:
                    if (path2D.getCurrentPoint() != null) {
                        path.addCommand(new ClosePathCommand());
                        path2D.closePath();
                    }
                    isClosed = true;
                    break;
                default:
                    break;
            }
        }

        if (!isClosed) {
            handleClosedShape(opt, path, path2D);
        }

        final Rectangle2D bounds = getBounds(opt, path2D);

        path.setW((int)Math.rint(bounds.getWidth()));
        path.setH((int)Math.rint(bounds.getHeight()));

        return cusGeo;
    }

    private static Rectangle2D getBounds(AbstractEscherOptRecord opt, Path2D path2D) {
        EscherSimpleProperty geoLeft = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__LEFT);
        EscherSimpleProperty geoRight = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__RIGHT);
        EscherSimpleProperty geoTop = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__TOP);
        EscherSimpleProperty geoBottom = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__BOTTOM);

        if (geoLeft != null && geoRight != null && geoTop != null && geoBottom != null) {
            final Rectangle2D bounds = new Rectangle2D.Double();
            bounds.setFrameFromDiagonal(
                    new Point2D.Double(geoLeft.getPropertyValue(), geoTop.getPropertyValue()),
                    new Point2D.Double(geoRight.getPropertyValue(), geoBottom.getPropertyValue())
            );
            return bounds;
        } else {
            return path2D.getBounds2D();
        }
    }

    private static void handleClosedShape(AbstractEscherOptRecord opt, Path path, Path2D path2D) {
        EscherSimpleProperty shapePath = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__SHAPEPATH);
        HSLFFreeformShape.ShapePath sp = HSLFFreeformShape.ShapePath.valueOf(shapePath == null ? 1 : shapePath.getPropertyValue());
        if (sp == LINES_CLOSED || sp == CURVES_CLOSED) {
            path.addCommand(new ClosePathCommand());
            path2D.closePath();
        }
    }

    private static void handleMoveTo(Iterator<byte[]> vertIter, int[] xyPoints, Path path, Path2D path2D) {
        if (!vertIter.hasNext()) {
            return;
        }
        final MoveToCommand m = new MoveToCommand();
        m.setPt(fillPoint(vertIter.next(), xyPoints));
        path.addCommand(m);
        path2D.moveTo(xyPoints[0], xyPoints[1]);
    }

    private static void handleLineTo(Iterator<byte[]> vertIter, int[] xyPoints, Path path, Path2D path2D) {
        if (!vertIter.hasNext()) {
            return;
        }
        handleMoveTo0(path, path2D);

        final LineToCommand m = new LineToCommand();
        m.setPt(fillPoint(vertIter.next(), xyPoints));
        path.addCommand(m);
        path2D.lineTo(xyPoints[0], xyPoints[1]);
    }

    private static void handleCurveTo(Iterator<byte[]> vertIter, int[] xyPoints, Path path, Path2D path2D) {
        if (!vertIter.hasNext()) {
            return;
        }
        handleMoveTo0(path, path2D);

        final CurveToCommand m = new CurveToCommand();

        int[] pts = new int[6];
        AdjustPoint[] ap = new AdjustPoint[3];

        for (int i=0; vertIter.hasNext() && i<3; i++) {
            ap[i] = fillPoint(vertIter.next(), xyPoints);
            pts[i*2] = xyPoints[0];
            pts[i*2+1] = xyPoints[1];
        }

        m.setPt1(ap[0]);
        m.setPt2(ap[1]);
        m.setPt3(ap[2]);

        path.addCommand(m);
        path2D.curveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
    }

    /**
     * Sometimes the path2D is not initialized - this initializes it with the 0,0 position
     */
    private static void handleMoveTo0(Path moveLst, Path2D path2D) {
        if (path2D.getCurrentPoint() == null) {
            final MoveToCommand m = new MoveToCommand();

            AdjustPoint pt = new AdjustPoint();
            pt.setX("0");
            pt.setY("0");
            m.setPt(pt);
            moveLst.addCommand(m);
            path2D.moveTo(0, 0);
        }
    }

    private static void handleEscapeInfo(Path pathCT, Path2D path2D, byte[] segElem, Iterator<byte[]> vertIter) {
        EscapeInfo ei = getEscapeInfo(segElem);
        if (ei == null) {
            return;
        }
        switch (ei) {
            case EXTENSION:
                break;
            case ANGLE_ELLIPSE_TO:
                break;
            case ANGLE_ELLIPSE:
                break;
            case ARC_TO: {
                // The first two POINT values specify the bounding rectangle of the ellipse.
                // The second two POINT values specify the radial vectors for the ellipse.
                // The radial vectors are cast from the center of the bounding rectangle.
                // The path starts at the POINT where the first radial vector intersects the
                // bounding rectangle and goes to the POINT where the second radial vector
                // intersects the bounding rectangle. The drawing direction is always counterclockwise.
                // If the path has already been started, a line is drawn from the last POINT to
                // the starting POINT of the arc; otherwise, a new path is started.
                // The number of arc segments drawn equals the number of segments divided by four.

                int[] r1 = new int[2], r2 = new int[2], start = new int[2], end = new int[2];
                fillPoint(vertIter.next(), r1);
                fillPoint(vertIter.next(), r2);
                fillPoint(vertIter.next(), start);
                fillPoint(vertIter.next(), end);

                Arc2D arc2D = new Arc2D.Double();
                Rectangle2D.Double bounds = new Rectangle2D.Double();
                bounds.setFrameFromDiagonal(xy2p(r1), xy2p(r2));
                arc2D.setFrame(bounds);
                arc2D.setAngles(xy2p(start), xy2p(end));
                path2D.append(arc2D, true);


                ArcToCommand arcTo = new ArcToCommand();
                arcTo.setHR(d2s(bounds.getHeight()/2.0));
                arcTo.setWR(d2s(bounds.getWidth()/2.0));

                arcTo.setStAng(d2s(-arc2D.getAngleStart()*60000.));
                arcTo.setSwAng(d2s(-arc2D.getAngleExtent()*60000.));

                pathCT.addCommand(arcTo);

                break;
            }
            case ARC:
                break;
            case CLOCKWISE_ARC_TO:
                break;
            case CLOCKWISE_ARC:
                break;
            case ELLIPTICAL_QUADRANT_X:
                break;
            case ELLIPTICAL_QUADRANT_Y:
                break;
            case QUADRATIC_BEZIER:
                break;
            case NO_FILL:
                break;
            case NO_LINE:
                break;
            case AUTO_LINE:
                break;
            case AUTO_CURVE:
                break;
            case CORNER_LINE:
                break;
            case CORNER_CURVE:
                break;
            case SMOOTH_LINE:
                break;
            case SMOOTH_CURVE:
                break;
            case SYMMETRIC_LINE:
                break;
            case SYMMETRIC_CURVE:
                break;
            case FREEFORM:
                break;
            case FILL_COLOR:
                break;
            case LINE_COLOR:
                break;
            default:
                break;
        }
    }

    private static String d2s(double d) {
        return Integer.toString((int)Math.rint(d));
    }

    private static Point2D xy2p(int[] xyPoints) {
        return new Point2D.Double(xyPoints[0],xyPoints[1]);
    }

    private static PathInfo getPathInfo(byte[] elem) {
        int elemUS = LittleEndian.getUShort(elem, 0);
        int pathInfo = PATH_INFO.getValue(elemUS);
        return PathInfo.valueOf(pathInfo);
    }

    private static EscapeInfo getEscapeInfo(byte[] elem) {
        int elemUS = LittleEndian.getUShort(elem, 0);
        int escInfo = ESCAPE_INFO.getValue(elemUS);
        return EscapeInfo.valueOf(escInfo);
    }


    private static AdjustPoint fillPoint(byte[] xyMaster, int[] xyPoints) {
        if (xyMaster == null || xyPoints == null) {
            LOG.atWarn().log("Master bytes or points not set - ignore point");
            return null;
        }
        if ((xyMaster.length != 4 && xyMaster.length != 8) || xyPoints.length != 2) {
            LOG.atWarn().log("Invalid number of master bytes for a single point - ignore point");
            return null;
        }

        int x, y;
        if (xyMaster.length == 4) {
            x = LittleEndian.getShort(xyMaster, 0);
            y = LittleEndian.getShort(xyMaster, 2);
        } else {
            x = LittleEndian.getInt(xyMaster, 0);
            y = LittleEndian.getInt(xyMaster, 4);
        }

        xyPoints[0] = x;
        xyPoints[1] = y;

        return toPoint(xyPoints);
    }

    private static AdjustPoint toPoint(int[] xyPoints) {
        AdjustPoint pt = new AdjustPoint();
        pt.setX(Integer.toString(xyPoints[0]));
        pt.setY(Integer.toString(xyPoints[1]));
        return pt;
    }
}
