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

import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readRectF;
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.poi.hemf.draw.HemfDrawProperties;
import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.hemf.record.emf.HemfFill;
import org.apache.poi.hwmf.record.HwmfRegionMode;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInputStream;

@SuppressWarnings("WeakerAccess")
public class HemfPlusMisc {
    public interface EmfPlusObjectId {
        BitField OBJECT_ID = BitFieldFactory.getInstance(0x00FF);

        int getFlags();

        /**
         * The index in the EMF+ Object Table to associate with the object
         * created by this record. The value MUST be zero to 63, inclusive.
         */
        default int getObjectId() {
            return OBJECT_ID.getValue(getFlags());
        }
    }

    public enum CombineMode {
        REPLACE(0x00000000, HwmfRegionMode.RGN_COPY),
        INTERSECT(0x00000001, HwmfRegionMode.RGN_AND),
        UNION(0x00000002, HwmfRegionMode.RGN_OR),
        XOR(0x00000003, HwmfRegionMode.RGN_XOR),
        EXCLUDE(0x00000004, HwmfRegionMode.RGN_DIFF),
        COMPLEMENT(0x00000005, HwmfRegionMode.RGN_COMPLEMENT)
        ;

        public final int id;
        public final HwmfRegionMode regionMode;

        CombineMode(int id, HwmfRegionMode regionMode) {
            this.id = id;
            this.regionMode = regionMode;
        }

        public static CombineMode valueOf(int id) {
            for (CombineMode wrt : values()) {
                if (wrt.id == id) return wrt;
            }
            return null;
        }
    }


    public static abstract class EmfPlusFlagOnly implements HemfPlusRecord {
        private int flags;
        private HemfPlusRecordType recordType;

        private static final int[] FLAGS_MASK = { 0x0F00 };
        private static final String[] FLAGS_NAMES = { "COMBINE_MODE" };

        @Override
        public int getFlags() {
            return flags;
        }

        @Override
        public final HemfPlusRecordType getEmfPlusRecordType() {
            return recordType;
        }

        @Override
        public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
            this.flags = flags;
            assert(dataSize == 0);
            recordType = HemfPlusRecordType.getById(recordId);
            return 0;
        }

        @Override
        public HemfPlusRecordType getGenericRecordType() {
            return getEmfPlusRecordType();
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "flags", getBitsAsString(this::getFlags,FLAGS_MASK,FLAGS_NAMES)
            );
        }
    }

    public static class EmfPlusEOF extends EmfPlusFlagOnly {
    }

    /**
     * The EmfPlusSetPixelOffsetMode record specifies how pixels are centered with respect to the
     * coordinates of the drawing surface.
     */
    public static class EmfPlusSetPixelOffsetMode extends EmfPlusFlagOnly {
    }

    /**
     * The EmfPlusSetAntiAliasMode record specifies the anti-aliasing mode for text output.
     */
    public static class EmfPlusSetAntiAliasMode extends EmfPlusFlagOnly {
    }

    /**
     * The EmfPlusSetCompositingMode record specifies how source colors are combined with background colors.
     */
    public static class EmfPlusSetCompositingMode extends EmfPlusFlagOnly {
    }

    /**
     * The EmfPlusSetCompositingQuality record specifies the desired level of quality for creating
     * composite images from multiple objects.
     */
    public static class EmfPlusSetCompositingQuality extends EmfPlusFlagOnly {
    }

    /**
     * The EmfPlusSetInterpolationMode record specifies how image scaling, including stretching and
     * shrinking, is performed.
     */
    public static class EmfPlusSetInterpolationMode extends EmfPlusFlagOnly {
    }

    /**
     * The EmfPlusGetDC record specifies that subsequent EMF records encountered in the metafile
     * SHOULD be processed.
     */
    public static class EmfPlusGetDC extends EmfPlusFlagOnly {
        @Override
        public void draw(HemfGraphics ctx) {
            ctx.setRenderState(HemfGraphics.EmfRenderState.EMF_DCONTEXT);
        }

        @Override
        public void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
            renderState[0] = HemfGraphics.EmfRenderState.EMF_DCONTEXT;
        }
    }

    /**
     * The EmfPlusSetTextRenderingHint record specifies the quality of text rendering, including the type
     * of anti-aliasing.
     */
    public static class EmfPlusSetTextRenderingHint extends EmfPlusFlagOnly {
    }

    /**
     * The EmfPlusResetWorldTransform record resets the current world space transform to the identify matrix.
     */
    public static class EmfPlusResetWorldTransform extends EmfPlusFlagOnly {
        @Override
        public void draw(HemfGraphics ctx) {
            HemfDrawProperties prop = ctx.getProperties();
            prop.clearTransform();
            ctx.updateWindowMapMode();
        }
    }


    /**
     * The EmfPlusSetWorldTransform record sets the world transform according to the values in a
     * specified transform matrix.
     */
    public static class EmfPlusSetWorldTransform implements HemfPlusRecord {
        private int flags;
        private final AffineTransform matrixData = new AffineTransform();

        @Override
        public HemfPlusRecordType getEmfPlusRecordType() {
            return HemfPlusRecordType.setWorldTransform;
        }

        @Override
        public int getFlags() {
            return flags;
        }

        @Override
        public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
            this.flags = flags;

            return HemfFill.readXForm(leis, matrixData);
        }

        public AffineTransform getMatrixData() {
            return matrixData;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            HemfDrawProperties prop = ctx.getProperties();
            prop.clearTransform();
            prop.addLeftTransform(getMatrixData());
            ctx.updateWindowMapMode();
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "flags", this::getFlags,
                "matrixData", this::getMatrixData
            );
        }
    }

    /**
     * The EmfPlusMultiplyWorldTransform record multiplies the current world space transform by a
     * specified transform matrix.
     */
    public static class EmfPlusMultiplyWorldTransform extends EmfPlusSetWorldTransform {
        @Override
        public HemfPlusRecordType getEmfPlusRecordType() {
            return HemfPlusRecordType.multiplyWorldTransform;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            AffineTransform tx = ctx.getInitTransform();
            tx.concatenate(getMatrixData());
            ctx.setTransform(tx);
            // don't call ctx.updateWindowMapMode();
        }
    }

    /**
     * The EmfPlusSetPageTransform record specifies scaling factors and units for converting page space
     * coordinates to device space coordinates.
     */
    public static class EmfPlusSetPageTransform implements HemfPlusRecord {
        private int flags;
        private double pageScale;

        @Override
        public HemfPlusRecordType getEmfPlusRecordType() {
            return HemfPlusRecordType.setPageTransform;
        }

        @Override
        public int getFlags() {
            return flags;
        }

        @Override
        public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
            this.flags = flags;
            pageScale = leis.readFloat();
            return LittleEndianConsts.INT_SIZE;
        }

        public double getPageScale() {
            return pageScale;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "flags", this::getFlags,
                "pageScale", this::getPageScale
            );
        }
    }

    /**
     * The EmfPlusSetClipRegion record combines the current clipping region with another graphics region.
     */
    public static class EmfPlusSetClipRegion extends EmfPlusSetClipPath {

    }


    /**
     * The EmfPlusSetClipPath record combines the current clipping region with a graphics path.
     */
    public static class EmfPlusSetClipPath extends EmfPlusFlagOnly implements EmfPlusObjectId {
        private static final BitField COMBINE_MODE = BitFieldFactory.getInstance(0x0F00);

        public CombineMode getCombineMode() {
            return CombineMode.valueOf(COMBINE_MODE.getValue(getFlags()));
        }

        @Override
        public void draw(HemfGraphics ctx) {
            HemfDrawProperties prop = ctx.getProperties();
            ctx.applyPlusObjectTableEntry(getObjectId());
            Shape clip = prop.getPath();
            ctx.setClip(clip, clip == null ? HwmfRegionMode.RGN_COPY : getCombineMode().regionMode, false);
        }
    }

    /** The EmfPlusSetClipRect record combines the current clipping region with a rectangle. */
    @SuppressWarnings("unused")
    public static class EmfPlusSetClipRect implements HemfPlusRecord {
        private static final BitField COMBINE_MODE = BitFieldFactory.getInstance(0x0F00);

        private static final int[] FLAGS_MASK = { 0x0F00 };
        private static final String[] FLAGS_NAMES = { "COMBINE_MODE" };

        private int flags;
        private final Rectangle2D clipRect = new Rectangle2D.Double();

        @Override
        public HemfPlusRecordType getEmfPlusRecordType() {
            return HemfPlusRecordType.setClipRect;
        }

        @Override
        public int getFlags() {
            return flags;
        }

        public CombineMode getCombineMode() {
            return CombineMode.valueOf(COMBINE_MODE.getValue(getFlags()));
        }

        @Override
        public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
            this.flags = flags;

            // An EmfPlusRectF object that defines the rectangle to use in the CombineMode operation.
            return readRectF(leis, clipRect);
        }

        public Rectangle2D getClipRect() {
            return clipRect;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "flags", getBitsAsString(this::getFlags, FLAGS_MASK, FLAGS_NAMES),
                "clipRect", this::getClipRect
            );
        }
    }


    /** The EmfPlusResetClip record resets the current clipping region for the world space to infinity. */
    public static class EmfPlusResetClip extends EmfPlusFlagOnly {

    }

    /**
     * The EmfPlusSave record saves the graphics state, identified by a specified index, on a stack of saved
     * graphics states.
     */
    public static class EmfPlusSave implements HemfPlusRecord {
        private int flags;
        private int stackIndex;

        @Override
        public HemfPlusRecordType getEmfPlusRecordType() {
            return HemfPlusRecordType.save;
        }

        @Override
        public int getFlags() {
            return flags;
        }

        public int getStackIndex() {
            return stackIndex;
        }

        @Override
        public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
            this.flags = flags;

            // A 32-bit unsigned integer that specifies a level to associate with the graphics state.
            // The level value can be used by a subsequent EmfPlusRestore record operation to retrieve the graphics state.
            stackIndex = leis.readInt();

            return LittleEndianConsts.INT_SIZE;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.savePlusProperties(getStackIndex());
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "flags", this::getFlags,
                "stackIndex", this::getStackIndex
            );
        }
    }

    /**
     * The EmfPlusRestore record restores the graphics state, identified by a specified index, from a stack
     * of saved graphics states.
     */
    public static class EmfPlusRestore extends EmfPlusSave {
        @Override
        public HemfPlusRecordType getEmfPlusRecordType() {
            return HemfPlusRecordType.restore;
        }

        @Override
        public void draw(HemfGraphics ctx) {
            ctx.restorePlusProperties(getStackIndex());
        }
    }

    /** The EmfPlusSetRenderingOrigin record specifies the rendering origin for graphics output. */
    public static class EmfPlusSetRenderingOrigin implements HemfPlusRecord {
        int flags;
        Point2D origin = new Point2D.Double();

        @Override
        public HemfPlusRecordType getEmfPlusRecordType() {
            return HemfPlusRecordType.setRenderingOrigin;
        }

        @Override
        public int getFlags() {
            return flags;
        }

        public Point2D getOrigin() {
            return origin;
        }

        @Override
        public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
            this.flags = flags;

            // error in the MS-EMFPLUS docs - its a signed integer instead of an unsigned
            // A 32-bit signed integer that defines the horizontal coordinate value of the rendering origin.
            int x = leis.readInt();
            // A 32-bit signed integer that defines the vertical coordinate value of the rendering origin.
            int y = leis.readInt();

            origin.setLocation(x,y);

            return LittleEndianConsts.INT_SIZE*2L;
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "flags", this::getFlags,
                "origin", this::getOrigin
            );
        }
    }

}
