/* ====================================================================
   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.hemf.record.emf;

import static org.apache.poi.hwmf.record.HwmfDraw.normalizeBounds;
import static org.apache.poi.util.GenericRecordUtil.getEnumBitsAsString;

import java.awt.Shape;
import java.awt.geom.Arc2D;
import java.awt.geom.Dimension2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.IntStream;

import org.apache.poi.hemf.draw.HemfDrawProperties;
import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.hwmf.draw.HwmfGraphics.FillDrawStyle;
import org.apache.poi.hwmf.record.HwmfDraw;
import org.apache.poi.hwmf.record.HwmfDraw.WmfSelectObject;
import org.apache.poi.util.GenericRecordJsonWriter;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInputStream;

public final class HemfDraw {
    private HemfDraw() {}

    /**
     * The EMR_SELECTOBJECT record adds a graphics object to the current metafile playback device
     * context. The object is specified either by its index in the EMF Object Table or by its
     * value from the StockObject enumeration.
     */
    public static class EmfSelectObject extends WmfSelectObject implements HemfRecord {

        private static final int[] IDX_MASKS = IntStream.rangeClosed(0x80000000,0x80000013).toArray();

        private static final String[] IDX_NAMES = {
            "WHITE_BRUSH",
            "LTGRAY_BRUSH",
            "GRAY_BRUSH",
            "DKGRAY_BRUSH",
            "BLACK_BRUSH",
            "NULL_BRUSH",
            "WHITE_PEN",
            "BLACK_PEN",
            "NULL_PEN",
            // 0x80000009 is not a valid stock object
            "INVALID",
            "OEM_FIXED_FONT",
            "ANSI_FIXED_FONT",
            "ANSI_VAR_FONT",
            "SYSTEM_FONT",
            "DEVICE_DEFAULT_FONT",
            "DEFAULT_PALETTE",
            "SYSTEM_FIXED_FONT",
            "DEFAULT_GUI_FONT",
            "DC_BRUSH",
            "DC_PEN"
        };

        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.selectObject;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            // A 32-bit unsigned integer that specifies either the index of a graphics object in the
            // EMF Object Table or the index of a stock object from the StockObject enumeration.
            objectIndex = leis.readInt();
            return LittleEndianConsts.INT_SIZE;
        }

        @Override
        public String toString() {
            return GenericRecordJsonWriter.marshal(this);
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "objectIndex", getEnumBitsAsString(this::getObjectIndex, IDX_MASKS, IDX_NAMES)
            );
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }


    /** The EMR_POLYBEZIER record specifies one or more Bezier curves. */
    public static class EmfPolyBezier extends HwmfDraw.WmfPolygon implements HemfRecord {
        private final Rectangle2D bounds = new Rectangle2D.Double();

        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyBezier;
        }

        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointL(leis, point);
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);

            /* A 32-bit unsigned integer that specifies the number of points in the points
             * array. This value MUST be one more than three times the number of curves to
             * be drawn, because each Bezier curve requires two control points and an
             * endpoint, and the initial curve requires an additional starting point.
             *
             * Line width | Device supports wideline | Maximum points allowed
             *    1       |            n/a           |          16K
             *   > 1      |            yes           |          16K
             *   > 1      |             no           |         1360
             *
             * Any extra points MUST be ignored.
             */
            final int count = (int)leis.readUInt();
            final int points = Math.min(count, 16384);
            size += LittleEndianConsts.INT_SIZE;

            poly = new Path2D.Double(Path2D.WIND_EVEN_ODD, points+2);

            /* Cubic Bezier curves are defined using the endpoints and control points
             * specified by the points field. The first curve is drawn from the first
             * point to the fourth point, using the second and third points as control
             * points. Each subsequent curve in the sequence needs exactly three more points:
             * the ending point of the previous curve is used as the starting point,
             * the next two points in the sequence are control points,
             * and the third is the ending point.
             * The cubic Bezier curves SHOULD be drawn using the current pen.
             */

            Point2D[] pnt = {new Point2D.Double(), new Point2D.Double(), new Point2D.Double()};

            int i=0;
            if (hasStartPoint()) {
                if (i < points) {
                    size += readPoint(leis, pnt[0]);
                    poly.moveTo(pnt[0].getX(), pnt[0].getY());
                    i++;
                }
            } else {
                poly.moveTo(0, 0);
            }

            for (; i+2<points; i+=3) {
                size += readPoint(leis, pnt[0]);
                size += readPoint(leis, pnt[1]);
                size += readPoint(leis, pnt[2]);

                poly.curveTo(
                    pnt[0].getX(),pnt[0].getY(),
                    pnt[1].getX(),pnt[1].getY(),
                    pnt[2].getX(),pnt[2].getY()
                );
            }

            return size;
        }

        /**
         * @return true, if start point is in the list of points. false, if start point is taken from the context
         */
        protected boolean hasStartPoint() {
            return true;
        }

        @Override
        protected FillDrawStyle getFillDrawStyle() {
            // The cubic Bezier curves SHOULD be drawn using the current pen.
            return FillDrawStyle.DRAW;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(poly, !hasStartPoint()), getFillDrawStyle());
        }

        public Rectangle2D getBounds() {
            return bounds;
        }

        @Override
        protected boolean addClose() {
            return false;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "base", super::getGenericProperties,
                "bounds", this::getBounds
            );
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_POLYBEZIER16 record specifies one or more Bezier curves.
     * The curves are drawn using the current pen.
     */
    public static class EmfPolyBezier16 extends EmfPolyBezier {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyBezier16;
        }

        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointS(leis, point);
        }
    }


    /**
     * The EMR_POLYGON record specifies a polygon consisting of two or more vertexes connected by
     * straight lines.
     */
    public static class EmfPolygon extends HwmfDraw.WmfPolygon implements HemfRecord {
        private final Rectangle2D bounds = new Rectangle2D.Double();

        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polygon;
        }

        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointL(leis, point);
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);

            // see PolyBezier about limits
            final int count = (int)leis.readUInt();
            final int points = Math.min(count, 16384);
            size += LittleEndianConsts.INT_SIZE;

            poly = new Path2D.Double(Path2D.WIND_EVEN_ODD, points);

            Point2D pnt = new Point2D.Double();
            for (int i=0; i<points; i++) {
                size += readPoint(leis, pnt);
                if (i==0) {
                    if (hasStartPoint()) {
                        poly.moveTo(pnt.getX(), pnt.getY());
                    } else {
                        // if this path is connected to the current position (= has no start point)
                        // the first entry is a dummy entry and will be skipped later
                        poly.moveTo(0,0);
                        poly.lineTo(pnt.getX(), pnt.getY());
                    }
                } else {
                    poly.lineTo(pnt.getX(), pnt.getY());
                }
            }

            return size;
        }

        /**
         * @return true, if start point is in the list of points. false, if start point is taken from the context
         */
        protected boolean hasStartPoint() {
            return true;
        }

        @Override
        protected FillDrawStyle getFillDrawStyle() {
            // The polygon SHOULD be outlined using the current pen and filled using the current brush and
            // polygon fill mode. The polygon SHOULD be closed automatically by drawing a line from the last
            // vertex to the first.
            return FillDrawStyle.FILL_DRAW;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(poly, false), getFillDrawStyle());
        }

        public Rectangle2D getBounds() {
            return bounds;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "base", super::getGenericProperties,
                "bounds", this::getBounds
            );
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_POLYGON16 record specifies a polygon consisting of two or more vertexes connected by straight lines.
     * The polygon is outlined by using the current pen and filled by using the current brush and polygon fill mode.
     * The polygon is closed automatically by drawing a line from the last vertex to the first
     */
    public static class EmfPolygon16 extends EmfPolygon {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polygon16;
        }

        @Override
        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointS(leis, point);
        }
    }

    /**
     * The EMR_POLYLINE record specifies a series of line segments by connecting the points in the
     * specified array.
     */
    public static class EmfPolyline extends EmfPolygon {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyline;
        }

        @Override
        protected FillDrawStyle getFillDrawStyle() {
            // The line segments SHOULD be drawn using the current pen.
            return FillDrawStyle.DRAW;
        }

        @Override
        protected boolean addClose() {
            return false;
        }
    }

    /**
     * The EMR_POLYLINE16 record specifies a series of line segments by connecting the points in the
     * specified array.
     */
    public static class EmfPolyline16 extends EmfPolyline {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyline16;
        }

        @Override
        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointS(leis, point);
        }
    }

    /**
     * The EMR_POLYBEZIERTO record specifies one or more Bezier curves based upon the current
     * position.
     */
    public static class EmfPolyBezierTo extends EmfPolyBezier {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyBezierTo;
        }

        @Override
        protected boolean hasStartPoint() {
            return false;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            polyTo(ctx, poly, getFillDrawStyle());
        }
    }

    /**
     * The EMR_POLYBEZIERTO16 record specifies one or more Bezier curves based on the current
     * position.
     */
    public static class EmfPolyBezierTo16 extends EmfPolyBezierTo {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyBezierTo16;
        }

        @Override
        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointS(leis, point);
        }
    }

    /** The EMR_POLYLINETO record specifies one or more straight lines based upon the current position. */
    public static class EmfPolylineTo extends EmfPolyline {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polylineTo;
        }

        @Override
        protected boolean hasStartPoint() {
            return false;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            polyTo(ctx, poly, getFillDrawStyle());
        }
    }

    /**
     * The EMR_POLYLINETO16 record specifies one or more straight lines based upon the current position.
     * A line is drawn from the current position to the first point specified by the points field by using the
     * current pen. For each additional line, drawing is performed from the ending point of the previous
     * line to the next point specified by points.
     */
    public static class EmfPolylineTo16 extends EmfPolylineTo {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polylineTo16;
        }

        @Override
        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointS(leis, point);
        }
    }

    /**
     * The EMR_POLYPOLYGON record specifies a series of closed polygons.
     */
    public static class EmfPolyPolygon extends HwmfDraw.WmfPolyPolygon implements HemfRecord {
        private final Rectangle2D bounds = new Rectangle2D.Double();

        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyPolygon;
        }

        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointL(leis, point);
        }

        @SuppressWarnings("unused")
        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);

            // A 32-bit unsigned integer that specifies the number of polygons.
            long numberOfPolygons = leis.readUInt();
            // A 32-bit unsigned integer that specifies the total number of points in all polygons.
            long count = Math.min(16384, leis.readUInt());

            size += 2 * LittleEndianConsts.INT_SIZE;

            // An array of 32-bit unsigned integers that specifies the point count for each polygon.
            long[] polygonPointCount = new long[(int)numberOfPolygons];

            size += numberOfPolygons * LittleEndianConsts.INT_SIZE;

            for (int i=0; i<numberOfPolygons; i++) {
                polygonPointCount[i] = leis.readUInt();
            }

            Point2D pnt = new Point2D.Double();
            for (long nPoints : polygonPointCount) {
                // An array of WMF PointL objects that specifies the points for all polygons in logical units.
                // The number of points is specified by the Count field value.
                Path2D poly = new Path2D.Double(Path2D.WIND_EVEN_ODD, (int)nPoints);
                for (int i=0; i<nPoints; i++) {
                    size += readPoint(leis, pnt);
                    if (i == 0) {
                        poly.moveTo(pnt.getX(), pnt.getY());
                    } else {
                        poly.lineTo(pnt.getX(), pnt.getY());
                    }
                }
                if (isClosed()) {
                    poly.closePath();
                }
                polyList.add(poly);
            }
            return size;
        }


        @Override
        public void draw(HemfGraphics ctx) {
            Shape shape = getShape(ctx);
            if (shape == null) {
                return;
            }

            ctx.draw(path -> path.append(shape, false), getFillDrawStyle());
        }

        public Rectangle2D getBounds() {
            return bounds;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "base", super::getGenericProperties,
                "bounds", this::getBounds
            );
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_POLYPOLYGON16 record specifies a series of closed polygons. Each polygon is outlined
     * using the current pen, and filled using the current brush and polygon fill mode.
     * The polygons drawn by this record can overlap.
     */
    public static class EmfPolyPolygon16 extends EmfPolyPolygon {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyPolygon16;
        }

        @Override
        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointS(leis, point);
        }
    }

    /**
     * The EMR_POLYPOLYLINE record specifies multiple series of connected line segments.
     */
    public static class EmfPolyPolyline extends EmfPolyPolygon {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyPolyline;
        }

        @Override
        protected boolean isClosed() {
            return false;
        }

        @Override
        protected FillDrawStyle getFillDrawStyle() {
            return FillDrawStyle.DRAW;
        }
    }

    /** The EMR_POLYPOLYLINE16 record specifies multiple series of connected line segments. */
    public static class EmfPolyPolyline16 extends EmfPolyPolyline {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyPolyline16;
        }

        @Override
        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointS(leis, point);
        }
    }

    /**
     * The EMR_SETPIXELV record defines the color of the pixel at the specified logical coordinates.
     */
    public static class EmfSetPixelV extends HwmfDraw.WmfSetPixel implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.setPixelV;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readPointL(leis, point);
            size += colorRef.init(leis);
            return size;
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_MOVETOEX record specifies coordinates of the new current position, in logical units.
     */
    public static class EmfSetMoveToEx extends HwmfDraw.WmfMoveTo implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.setMoveToEx;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return readPointL(leis, point);
        }

        @Override
        public void draw(final HemfGraphics ctx) {
            ctx.draw((path) -> path.moveTo(point.getX(), point.getY()), FillDrawStyle.NONE);
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_ARC record specifies an elliptical arc.
     * It resets the current position to the end point of the arc.
     */
    public static class EmfArc extends HwmfDraw.WmfArc implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.arc;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);
            size += readPointL(leis, startPoint);
            size += readPointL(leis, endPoint);
            return size;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_CHORD record specifies a chord, which is a region bounded by the intersection of an
     * ellipse and a line segment, called a secant. The chord is outlined by using the current pen
     * and filled by using the current brush.
     */
    public static class EmfChord extends HwmfDraw.WmfChord implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.chord;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);
            size += readPointL(leis, startPoint);
            size += readPointL(leis, endPoint);
            return size;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_PIE record specifies a pie-shaped wedge bounded by the intersection of an ellipse and two
     * radials. The pie is outlined by using the current pen and filled by using the current brush.
     */
    public static class EmfPie extends HwmfDraw.WmfPie implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.pie;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);
            size += readPointL(leis, startPoint);
            size += readPointL(leis, endPoint);
            return size;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_ELLIPSE record specifies an ellipse. The center of the ellipse is the center of the specified
     * bounding rectangle. The ellipse is outlined by using the current pen and is filled by using the current
     * brush.
     */
    public static class EmfEllipse extends HwmfDraw.WmfEllipse implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.ellipse;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return readRectL(leis, bounds);
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(getShape(), false), FillDrawStyle.FILL_DRAW);
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_RECTANGLE record draws a rectangle. The rectangle is outlined by using the current pen
     * and filled by using the current brush.
     */
    public static class EmfRectangle extends HwmfDraw.WmfRectangle implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.rectangle;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return readRectL(leis, bounds);
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(normalizeBounds(bounds), false), FillDrawStyle.FILL_DRAW);
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_ROUNDRECT record specifies a rectangle with rounded corners. The rectangle is outlined
     * by using the current pen and filled by using the current brush.
     */
    public static class EmfRoundRect extends HwmfDraw.WmfRoundRect implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.roundRect;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);

            // A 32-bit unsigned integer that defines the x-coordinate of the point.
            int width = (int)leis.readUInt();
            int height = (int)leis.readUInt();
            corners.setSize(width, height);

            return size + 2*LittleEndianConsts.INT_SIZE;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(getShape(), false), FillDrawStyle.FILL_DRAW);
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_LINETO record specifies a line from the current position up to, but not including, the
     * specified point. It resets the current position to the specified point.
     */
    public static class EmfLineTo extends HwmfDraw.WmfLineTo implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.lineTo;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return readPointL(leis, point);
        }

        @Override
        public void draw(final HemfGraphics ctx) {
            ctx.draw((path) -> path.lineTo(point.getX(), point.getY()), FillDrawStyle.DRAW);
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /**
     * The EMR_ARCTO record specifies an elliptical arc.
     * It resets the current position to the end point of the arc.
     */
    public static class EmfArcTo extends HwmfDraw.WmfArc implements HemfRecord {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.arcTo;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);
            size += readPointL(leis, startPoint);
            size += readPointL(leis, endPoint);
            return size;
        }

        @Override
        public void draw(final HemfGraphics ctx) {
            final Arc2D arc = getShape();
            ctx.draw((path) -> path.append(arc, true), getFillDrawStyle());
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    /** The EMR_POLYDRAW record specifies a set of line segments and Bezier curves. */
    public static class EmfPolyDraw extends HwmfDraw.WmfPolygon implements HemfRecord {
        private final Rectangle2D bounds = new Rectangle2D.Double();

        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyDraw;
        }

        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointL(leis, point);
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            long size = readRectL(leis, bounds);
            int count = (int)leis.readUInt();
            size += LittleEndianConsts.INT_SIZE;
            Point2D[] points = new Point2D[count];
            for (int i=0; i<count; i++) {
                points[i] = new Point2D.Double();
                size += readPoint(leis, points[i]);
            }

            poly = new Path2D.Double(Path2D.WIND_EVEN_ODD, count);

            for (int i=0; i<count; i++) {
                int mode = leis.readUByte();
                switch (mode & 0x06) {
                    // PT_LINETO
                    // Specifies that a line is to be drawn from the current position to this point, which
                    // then becomes the new current position.
                    case 0x02:
                        poly.lineTo(points[i].getX(), points[i].getY());
                        break;
                    // PT_BEZIERTO
                    // Specifies that this point is a control point or ending point for a Bezier curve.
                    // PT_BEZIERTO types always occur in sets of three.
                    // The current position defines the starting point for the Bezier curve.
                    // The first two PT_BEZIERTO points are the control points,
                    // and the third PT_BEZIERTO point is the ending point.
                    // The ending point becomes the new current position.
                    // If there are not three consecutive PT_BEZIERTO points, an error results.
                    case 0x04:
                        int mode2 = leis.readUByte();
                        int mode3 = leis.readUByte();
                        assert(mode2 == 0x04 && (mode3 == 0x04 || mode3 == 0x05));
                        if ((i + 2) >= points.length) {
                            throw new IllegalStateException("Points index causes index out of bounds");
                        }
                        poly.curveTo(
                            points[i].getX(), points[i].getY(),
                            points[i+1].getX(), points[i+1].getY(),
                            points[i+2].getX(), points[i+2].getY()
                        );
                        // update mode for closePath handling below
                        mode = mode3;
                        i+=2;
                        break;
                    // PT_MOVETO
                    // Specifies that this point starts a disjoint figure. This point becomes the new current position.
                    case 0x06:
                        poly.moveTo(points[i].getX(), points[i].getY());
                        break;
                    default:
                        // TODO: log error
                        break;
                }

                // PT_CLOSEFIGURE
                // A PT_LINETO or PT_BEZIERTO type can be combined with this value by using the bitwise operator OR
                // to indicate that the corresponding point is the last point in a figure and the figure is closed.
                // The current position is set to the ending point of the closing line.
                if ((mode & 0x01) == 0x01) {
                    this.poly.closePath();
                }
            }
            size += count;
            return size;
        }

        @Override
        protected FillDrawStyle getFillDrawStyle() {
            // Draws a set of line segments and Bezier curves.
            return FillDrawStyle.DRAW;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.draw(path -> path.append(poly, false), getFillDrawStyle());
        }

        public Rectangle2D getBounds() {
            return bounds;
        }

        @Override
        protected boolean addClose() {
            return false;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "base", super::getGenericProperties,
                "bounds", this::getBounds
            );
        }

        @Override
        public HemfRecordType getGenericRecordType() {
            return getEmfRecordType();
        }
    }

    public static class EmfPolyDraw16 extends EmfPolyDraw {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.polyDraw16;
        }

        protected long readPoint(LittleEndianInputStream leis, Point2D point) {
            return readPointS(leis, point);
        }
    }

    /**
     * This record opens a path bracket in the current playback device context.
     *
     * After a path bracket is open, an application can begin processing records to define
     * the points that lie in the path. An application MUST close an open path bracket by
     * processing the EMR_ENDPATH record.
     *
     * When an application processes the EMR_BEGINPATH record, all previous paths
     * MUST be discarded from the playback device context.
     */
    public static class EmfBeginPath implements HemfRecordWithoutProperties {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.beginPath;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return 0;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            final HemfDrawProperties prop = ctx.getProperties();
            prop.setPath(new Path2D.Double());
            prop.setUsePathBracket(true);
        }

        @Override
        public String toString() {
            return "{}";
        }
    }

    /**
     * This record closes a path bracket and selects the path defined by the bracket into
     * the playback device context.
     */
    public static class EmfEndPath implements HemfRecordWithoutProperties {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.endPath;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return 0;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            final HemfDrawProperties prop = ctx.getProperties();
            prop.setUsePathBracket(false);
        }

        @Override
        public String toString() {
            return "{}";
        }
    }

    /**
     * This record aborts a path bracket or discards the path from a closed path bracket.
     */
    public static class EmfAbortPath implements HemfRecordWithoutProperties {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.abortPath;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return 0;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            final HemfDrawProperties prop = ctx.getProperties();
            prop.setPath(null);
            prop.setUsePathBracket(false);
        }

        @Override
        public String toString() {
            return "{}";
        }
    }

    /**
     * This record closes an open figure in a path.
     *
     * Processing the EMR_CLOSEFIGURE record MUST close the figure by drawing a line
     * from the current position to the first point of the figure, and then it MUST connect
     * the lines by using the line join style. If a figure is closed by processing the
     * EMR_LINETO record instead of the EMR_CLOSEFIGURE record, end caps are
     * used to create the corner instead of a join.
     *
     * The EMR_CLOSEFIGURE record SHOULD only be used if there is an open path
     * bracket in the playback device context.
     *
     * A figure in a path is open unless it is explicitly closed by processing this record.
     * Note: A figure can be open even if the current point and the starting point of the
     * figure are the same.
     *
     * After processing the EMR_CLOSEFIGURE record, adding a line or curve to the path
     * MUST start a new figure.
     */
    public static class EmfCloseFigure implements HemfRecordWithoutProperties {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.closeFigure;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return 0;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            final HemfDrawProperties prop = ctx.getProperties();
            final Path2D path = prop.getPath();
            if (path != null && path.getCurrentPoint() != null) {
                path.closePath();
                prop.setLocation(path.getCurrentPoint());
            }
        }

        @Override
        public String toString() {
            return "{}";
        }
    }

    /**
     * This record transforms any curves in the selected path into the playback device
     * context; each curve MUST be turned into a sequence of lines.
     */
    public static class EmfFlattenPath implements HemfRecordWithoutProperties {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.flattenPath;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return 0;
        }
    }

    /**
     * This record redefines the current path as the area that would be painted if the path
     * were drawn using the pen currently selected into the playback device context.
     */
    public static class EmfWidenPath implements HemfRecordWithoutProperties {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.widenPath;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            return 0;
        }

        @Override
        public String toString() {
            return "{}";
        }
    }

    /**
     * The EMR_STROKEPATH record renders the specified path by using the current pen.
     */
    public static class EmfStrokePath implements HemfRecord {
        protected final Rectangle2D bounds = new Rectangle2D.Double();

        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.strokePath;
        }

        @Override
        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
            // A 128-bit WMF RectL object, which specifies bounding rectangle, in device units
            return (recordSize == 0) ? 0 : readRectL(leis, bounds);
        }

        @Override
        public void draw(HemfGraphics ctx) {
            HemfDrawProperties props = ctx.getProperties();
            Path2D path = props.getPath();
            path.setWindingRule(ctx.getProperties().getWindingRule());
            ctx.draw(path);
        }

        @Override
        public String toString() {
            return GenericRecordJsonWriter.marshal(this);
        }

        public Rectangle2D getBounds() {
            return bounds;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties("bounds", this::getBounds);
        }
    }


    /**
     * The EMR_FILLPATH record closes any open figures in the current path and fills the path's interior by
     * using the current brush and polygon-filling mode.
     */
    public static class EmfFillPath extends EmfStrokePath {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.fillPath;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            final HemfDrawProperties prop = ctx.getProperties();
            final Path2D origPath = prop.getPath();
            if (origPath.getCurrentPoint() == null) {
                return;
            }
            final Path2D path = (Path2D)origPath.clone();
            path.closePath();
            path.setWindingRule(ctx.getProperties().getWindingRule());
            ctx.fill(path);
        }
    }

    /**
     * The EMR_STROKEANDFILLPATH record closes any open figures in a path, strokes the outline of the
     * path by using the current pen, and fills its interior by using the current brush.
     */
    public static class EmfStrokeAndFillPath extends EmfStrokePath {
        @Override
        public HemfRecordType getEmfRecordType() {
            return HemfRecordType.strokeAndFillPath;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            HemfDrawProperties props = ctx.getProperties();
            Path2D path = props.getPath();
            path.closePath();
            path.setWindingRule(ctx.getProperties().getWindingRule());
            ctx.fill(path);
            ctx.draw(path);
        }
    }

    static long readRectL(LittleEndianInputStream leis, Rectangle2D bounds) {
        /* A 32-bit signed integer that defines the x coordinate, in logical coordinates,
         * of the ... corner of the rectangle.
         */
        final double left = leis.readInt();
        final double top = leis.readInt();
        final double right = leis.readInt();
        final double bottom = leis.readInt();
        bounds.setRect(left, top, right-left, bottom-top);

        return 4L * LittleEndianConsts.INT_SIZE;
    }

    static long readPointS(LittleEndianInputStream leis, Point2D point) {
        // x (2 bytes): A 16-bit signed integer that defines the horizontal (x) coordinate of the point.
        final int x = leis.readShort();
        // y (2 bytes): A 16-bit signed integer that defines the vertical (y) coordinate of the point.
        final int y = leis.readShort();
        point.setLocation(x, y);

        return 2L*LittleEndianConsts.SHORT_SIZE;

    }
    static long readPointL(LittleEndianInputStream leis, Point2D point) {
        // x (4 bytes): A 32-bit signed integer that defines the horizontal (x) coordinate of the point.
        final int x = leis.readInt();
        // y (4 bytes): A 32-bit signed integer that defines the vertical (y) coordinate of the point.
        final int y = leis.readInt();
        point.setLocation(x, y);

        return 2L*LittleEndianConsts.INT_SIZE;

    }

    static long readDimensionFloat(LittleEndianInputStream leis, Dimension2D dimension) {
        final double width = leis.readFloat();
        final double height = leis.readFloat();
        dimension.setSize(width, height);
        return 2L*LittleEndianConsts.INT_SIZE;
    }

    static long readDimensionInt(LittleEndianInputStream leis, Dimension2D dimension) {
        // although the spec says "use unsigned ints", there are examples out there using signed ints
        final double width = leis.readInt();
        final double height = leis.readInt();
        dimension.setSize(width, height);
        return 2L*LittleEndianConsts.INT_SIZE;
    }

    private static void polyTo(final HemfGraphics ctx, final Path2D poly, FillDrawStyle fillDrawStyle) {
        if (poly.getCurrentPoint() == null) {
            return;
        }

        final PathIterator pi = poly.getPathIterator(null);
        // ignore empty polys and dummy start point (moveTo)
        pi.next();
        if (pi.isDone()) {
            return;
        }

        ctx.draw((path) -> path.append(pi, true), fillDrawStyle);
    }
}
