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

import java.awt.Color;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.poi.hwmf.draw.HwmfDrawProperties;
import org.apache.poi.hwmf.draw.HwmfGraphics;
import org.apache.poi.hwmf.record.HwmfFill.ColorUsage;
import org.apache.poi.hwmf.record.HwmfFill.HwmfImageRecord;
import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode;
import org.apache.poi.util.Dimension2DDouble;
import org.apache.poi.util.GenericRecordJsonWriter;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInputStream;

@SuppressWarnings("WeakerAccess")
public class HwmfMisc {

    /**
     * The META_SAVEDC record saves the playback device context for later retrieval.
     */
    public static class WmfSaveDc implements HwmfRecord {
        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.saveDc;
        }

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

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.saveProperties();
        }

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

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return null;
        }
    }

    /**
     * The META_SETRELABS record is reserved and not supported.
     */
    public static class WmfSetRelabs implements HwmfRecord {
        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.setRelabs;
        }

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

        @Override
        public void draw(HwmfGraphics ctx) {

        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return null;
        }
    }

    /**
     * The META_RESTOREDC record restores the playback device context from a previously saved device
     * context.
     */
    public static class WmfRestoreDc implements HwmfRecord {

        /**
         * nSavedDC (2 bytes):  A 16-bit signed integer that defines the saved state to be restored. If this
         * member is positive, nSavedDC represents a specific instance of the state to be restored. If
         * this member is negative, nSavedDC represents an instance relative to the current state.
         */
        protected int nSavedDC;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.restoreDc;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            nSavedDC = leis.readShort();
            return LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.restoreProperties(nSavedDC);
        }

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

        public int getNSavedDC() {
            return nSavedDC;
        }

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

    /**
     * The META_SETBKCOLOR record sets the background color in the playback device context to a
     * specified color, or to the nearest physical color if the device cannot represent the specified color.
     */
    public static class WmfSetBkColor implements HwmfRecord {

        protected final HwmfColorRef colorRef = new HwmfColorRef();

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.setBkColor;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            return colorRef.init(leis);
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.getProperties().setBackgroundColor(colorRef);
        }

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

        public HwmfColorRef getColorRef() {
            return colorRef;
        }

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

    /**
     * The META_SETBKMODE record defines the background raster operation mix mode in the playback
     * device context. The background mix mode is the mode for combining pens, text, hatched brushes,
     * and interiors of filled objects with background colors on the output surface.
     */
    public static class WmfSetBkMode implements HwmfRecord {

        /**
         * A 16-bit unsigned integer that defines background mix mode.
         */
        public enum HwmfBkMode {
            TRANSPARENT(0x0001), OPAQUE(0x0002);

            final int flag;
            HwmfBkMode(int flag) {
                this.flag = flag;
            }

            public static HwmfBkMode valueOf(int flag) {
                for (HwmfBkMode bs : values()) {
                    if (bs.flag == flag) return bs;
                }
                return null;
            }
        }

        protected HwmfBkMode bkMode;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.setBkMode;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            bkMode = HwmfBkMode.valueOf(leis.readUShort());
            return LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.getProperties().setBkMode(bkMode);
        }

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

        public HwmfBkMode getBkMode() {
            return bkMode;
        }

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

    /**
     * The META_SETLAYOUT record defines the layout orientation in the playback device context.
     * The layout orientation determines the direction in which text and graphics are drawn
     */
    public static class WmfSetLayout implements HwmfRecord {

        /**
         * A 16-bit unsigned integer that defines the layout of text and graphics.
         * LAYOUT_LTR = 0x0000
         * LAYOUT_RTL = 0x0001
         * LAYOUT_BITMAPORIENTATIONPRESERVED = 0x0008
         */
        private int layout;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.setLayout;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            layout = leis.readUShort();
            // A 16-bit field that MUST be ignored.
            /*int reserved =*/ leis.readShort();
            return 2*LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {

        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties("layout", () -> layout);
        }
    }

    /**
     * The META_SETMAPMODE record defines the mapping mode in the playback device context.
     * The mapping mode defines the unit of measure used to transform page-space units into
     * device-space units, and also defines the orientation of the device's x and y axes.
     */
    public static class WmfSetMapMode implements HwmfRecord {

        protected HwmfMapMode mapMode;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.setMapMode;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            mapMode = HwmfMapMode.valueOf(leis.readUShort());
            return LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.getProperties().setMapMode(mapMode);
            ctx.updateWindowMapMode();
        }

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

        public HwmfMapMode getMapMode() {
            return mapMode;
        }

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

    /**
     * The META_SETMAPPERFLAGS record defines the algorithm that the font mapper uses when it maps
     * logical fonts to physical fonts.
     */
    public static class WmfSetMapperFlags implements HwmfRecord {

        /**
         * A 32-bit unsigned integer that defines whether the font mapper should attempt to
         * match a font's aspect ratio to the current device's aspect ratio. If bit 0 is
         * set, the font mapper SHOULD select only fonts that match the aspect ratio of the
         * output device, as it is currently defined in the playback device context.
         */
        private long mapperValues;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.setMapperFlags;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            mapperValues = leis.readUInt();
            return LittleEndianConsts.INT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {

        }

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

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties("mapperValues", () -> mapperValues);
        }
    }

    /**
     * The META_SETROP2 record defines the foreground raster operation mix mode in the playback device
     * context. The foreground mix mode is the mode for combining pens and interiors of filled objects with
     * foreground colors on the output surface.
     */
    public static class WmfSetRop2 implements HwmfRecord {

        /** An unsigned integer that defines the foreground binary raster operation mixing mode */
        protected HwmfBinaryRasterOp drawMode;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.setRop2;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            drawMode = HwmfBinaryRasterOp.valueOf(leis.readUShort());
            return LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            HwmfDrawProperties prop = ctx.getProperties();
            prop.setRasterOp2(drawMode);
        }

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

        public HwmfBinaryRasterOp getDrawMode() {
            return drawMode;
        }

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

    /**
     * The META_SETSTRETCHBLTMODE record defines the bitmap stretching mode in the playback device
     * context.
     */
    public static class WmfSetStretchBltMode implements HwmfRecord {

        public enum StretchBltMode {
            /**
             * Performs a Boolean AND operation by using the color values for the eliminated and existing pixels.
             * If the bitmap is a monochrome bitmap, this mode preserves black pixels at the expense of white pixels.
             *
             * EMF name: STRETCH_ANDSCANS
             */
            BLACKONWHITE(0x0001),
            /**
             * Performs a Boolean OR operation by using the color values for the eliminated and existing pixels.
             * If the bitmap is a monochrome bitmap, this mode preserves white pixels at the expense of black pixels.
             *
             * EMF name: STRETCH_ORSCANS
             */
            WHITEONBLACK(0x0002),
            /**
             * Deletes the pixels. This mode deletes all eliminated lines of pixels without trying
             * to preserve their information.
             *
             * EMF name: STRETCH_DELETESCANS
             */
            COLORONCOLOR(0x0003),
            /**
             * Maps pixels from the source rectangle into blocks of pixels in the destination rectangle.
             * The average color over the destination block of pixels approximates the color of the source
             * pixels.
             *
             * After setting the HALFTONE stretching mode, the brush origin MUST be set to avoid misalignment
             * artifacts - in EMF this is done via EmfSetBrushOrgEx
             *
             * EMF name: STRETCH_HALFTONE
             */
            HALFTONE(0x0004);

            public final int flag;
            StretchBltMode(int flag) {
                this.flag = flag;
            }

            public static StretchBltMode valueOf(int flag) {
                for (StretchBltMode bs : values()) {
                    if (bs.flag == flag) return bs;
                }
                return null;
            }
        }

        protected StretchBltMode stretchBltMode;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.setStretchBltMode;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            stretchBltMode = StretchBltMode.valueOf(leis.readUShort());
            return LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {

        }

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

        public StretchBltMode getStretchBltMode() {
            return stretchBltMode;
        }

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

    /**
     * The META_DIBCREATEPATTERNBRUSH record creates a Brush Object with a
     * pattern specified by a DeviceIndependentBitmap (DIB) Object
     */
    public static class WmfDibCreatePatternBrush implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry {

        protected HwmfBrushStyle style;

        /**
         * A 16-bit unsigned integer that defines whether the Colors field of a DIB
         * Object contains explicit RGB values, or indexes into a palette.
         *
         * If the Style field specifies BS_PATTERN, a ColorUsage value of DIB_RGB_COLORS MUST be
         * used regardless of the contents of this field.
         *
         * If the Style field specified anything but BS_PATTERN, this field MUST be one of the ColorUsage values.
         */
        protected ColorUsage colorUsage;

        protected HwmfBitmapDib patternDib;
        private HwmfBitmap16 pattern16;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.dibCreatePatternBrush;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            style = HwmfBrushStyle.valueOf(leis.readUShort());
            colorUsage = ColorUsage.valueOf(leis.readUShort());
            int size = 2*LittleEndianConsts.SHORT_SIZE;
            switch (style) {
            case BS_SOLID:
            case BS_NULL:
            case BS_DIBPATTERN:
            case BS_DIBPATTERNPT:
            case BS_HATCHED:
            case BS_PATTERN:
                patternDib = new HwmfBitmapDib();
                size += patternDib.init(leis, (int)(recordSize-6-size));
                break;
            case BS_INDEXED:
            case BS_DIBPATTERN8X8:
            case BS_MONOPATTERN:
            case BS_PATTERN8X8:
                throw new RuntimeException("pattern not supported");
            }
            return size;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.addObjectTableEntry(this);
        }

        @Override
        public void applyObject(HwmfGraphics ctx) {
            if (patternDib != null && !patternDib.isValid()) {
                return;
            }
            HwmfDrawProperties prop = ctx.getProperties();
            prop.setBrushStyle(style);

            BufferedImage bufImg = getImage(
                prop.getBrushColor().getColor(),
                prop.getBackgroundColor().getColor(),
                prop.getBkMode() == HwmfBkMode.TRANSPARENT);

            prop.setBrushBitmap(bufImg);
        }

        @Override
        public BufferedImage getImage(Color foreground, Color background, boolean hasAlpha) {
            if (patternDib != null && patternDib.isValid()) {
                return patternDib.getImage(foreground, background, hasAlpha);
            } else if (pattern16 != null) {
                return pattern16.getImage();
            } else {
                return null;
            }
        }

        @Override
        public byte[] getBMPData() {
            if (patternDib != null && patternDib.isValid()) {
                return patternDib.getBMPData();
            } else if (pattern16 != null) {
                return null;
            } else {
                return null;
            }
        }

        public HwmfBrushStyle getStyle() {
            return style;
        }

        public ColorUsage getColorUsage() {
            return colorUsage;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "style", this::getStyle,
                "colorUsage", this::getColorUsage,
                "pattern", () -> (patternDib != null && patternDib.isValid()) ? patternDib : pattern16,
                "bmpData", this::getBMPData
            );
        }
    }

    /**
     * The META_DELETEOBJECT record deletes an object, including Bitmap16, Brush,
     * DeviceIndependentBitmap, Font, Palette, Pen, and Region. After the object is deleted,
     * its index in the WMF Object Table is no longer valid but is available to be reused.
     */
    public static class WmfDeleteObject implements HwmfRecord {
        /**
         * A 16-bit unsigned integer used to index into the WMF Object Table to
         * get the object to be deleted.
         */
        protected int objectIndex;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.deleteObject;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            objectIndex = leis.readUShort();
            return LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            /* TODO:
             * The object specified by this record MUST be deleted from the EMF Object Table.
             * If the deleted object is currently selected in the playback device context,
             * the default object for that graphics property MUST be restored.
             */

            ctx.unsetObjectTableEntry(objectIndex);
        }

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

        public int getObjectIndex() {
            return objectIndex;
        }

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

    public static class WmfCreatePatternBrush implements HwmfRecord, HwmfObjectTableEntry {

        private HwmfBitmap16 pattern;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.createPatternBrush;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            pattern = new HwmfBitmap16(true);
            return pattern.init(leis);
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.addObjectTableEntry(this);
        }

        @Override
        public void applyObject(HwmfGraphics ctx) {
            HwmfDrawProperties dp = ctx.getProperties();
            dp.setBrushBitmap(pattern.getImage());
            dp.setBrushStyle(HwmfBrushStyle.BS_PATTERN);
        }

        public HwmfBitmap16 getPattern() {
            return pattern;
        }

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

    public static class WmfCreatePenIndirect implements HwmfRecord, HwmfObjectTableEntry {

        protected HwmfPenStyle penStyle;

        protected final Dimension2D dimension = new Dimension2DDouble();
        /**
         * A 32-bit ColorRef Object that specifies the pen color value.
         */
        protected final HwmfColorRef colorRef = new HwmfColorRef();

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.createPenIndirect;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            penStyle = HwmfPenStyle.valueOf(leis.readUShort());
            // A 32-bit PointS Object that specifies a point for the object dimensions.
            // The x-coordinate is the pen width. The y-coordinate is ignored.
            int xWidth = leis.readShort();
            int yWidth = leis.readShort();
            dimension.setSize(xWidth, yWidth);

            int size = colorRef.init(leis);
            return size+3*LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.addObjectTableEntry(this);
        }

        @Override
        public void applyObject(HwmfGraphics ctx) {
            HwmfDrawProperties p = ctx.getProperties();
            p.setPenStyle(penStyle);
            p.setPenColor(colorRef);
            p.setPenWidth(dimension.getWidth());
        }

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

        public HwmfPenStyle getPenStyle() {
            return penStyle;
        }

        public Dimension2D getDimension() {
            return dimension;
        }

        public HwmfColorRef getColorRef() {
            return colorRef;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "penStyle", this::getPenStyle,
                "dimension", this::getDimension,
                "colorRef", this::getColorRef
            );
        }
    }

    /**
     * The META_CREATEBRUSHINDIRECT record creates a Brush Object
     * from a LogBrush Object.
     *
     * The following table shows the relationship between values in the BrushStyle,
     * ColorRef and BrushHatch fields in a LogBrush Object. Only supported brush styles are listed.
     *
     * <table summary="">
     * <tr>
     *   <th>BrushStyle</th>
     *   <th>ColorRef</th>
     *   <th>BrushHatch</th>
     * </tr>
     * <tr>
     *   <td>BS_SOLID</td>
     *   <td>SHOULD be a ColorRef Object, which determines the color of the brush.</td>
     *   <td>Not used, and SHOULD be ignored.</td>
     * </tr>
     * <tr>
     *   <td>BS_NULL</td>
     *   <td>Not used, and SHOULD be ignored.</td>
     *   <td>Not used, and SHOULD be ignored.</td>
     * </tr>
     * <tr>
     *   <td>BS_PATTERN</td>
     *   <td>Not used, and SHOULD be ignored.</td>
     *   <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created.</td>
     * </tr>
     * <tr>
     *   <td>BS_DIBPATTERN</td>
     *   <td>Not used, and SHOULD be ignored.</td>
     *   <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created</td>
     * </tr>
     * <tr>
     *   <td>BS_DIBPATTERNPT</td>
     *   <td>Not used, and SHOULD be ignored.</td>
     *   <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created.</td>
     * </tr>
     * <tr>
     *   <td>BS_HATCHED</td>
     *   <td>SHOULD be a ColorRef Object, which determines the foreground color of the hatch pattern.</td>
     *   <td>A value from the {@link HwmfHatchStyle} Enumeration that specifies the orientation of lines used to create the hatch.</td>
     * </tr>
     * </table>
     */
    public static class WmfCreateBrushIndirect implements HwmfRecord, HwmfObjectTableEntry {
        protected HwmfBrushStyle brushStyle;

        protected HwmfColorRef colorRef;

        protected HwmfHatchStyle brushHatch;

        @Override
        public HwmfRecordType getWmfRecordType() {
            return HwmfRecordType.createBrushIndirect;
        }

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            brushStyle = HwmfBrushStyle.valueOf(leis.readUShort());
            colorRef = new HwmfColorRef();
            int size = colorRef.init(leis);
            brushHatch = HwmfHatchStyle.valueOf(leis.readUShort());
            return size+2*LittleEndianConsts.SHORT_SIZE;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.addObjectTableEntry(this);
        }

        @Override
        public void applyObject(HwmfGraphics ctx) {
            HwmfDrawProperties p = ctx.getProperties();
            p.setBrushStyle(brushStyle);
            p.setBrushColor(colorRef);
            p.setBrushHatch(brushHatch);
        }

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

        public HwmfBrushStyle getBrushStyle() {
            return brushStyle;
        }

        public HwmfColorRef getColorRef() {
            return colorRef;
        }

        public HwmfHatchStyle getBrushHatch() {
            return brushHatch;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "brushStyle", this::getBrushStyle,
                "colorRef", this::getColorRef,
                "brushHatch", this::getBrushHatch
            );
        }
    }
}