/* ====================================================================
   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 static org.apache.poi.hwmf.record.HwmfDraw.readPointS;
import static org.apache.poi.hwmf.record.HwmfDraw.readRectS;
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hwmf.draw.HwmfDrawProperties;
import org.apache.poi.hwmf.draw.HwmfGraphics;
import org.apache.poi.hwmf.record.HwmfMisc.WmfSetMapMode;
import org.apache.poi.hwmf.usermodel.HwmfCharsetAware;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.GenericRecordJsonWriter;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInputStream;
import org.apache.poi.util.LocaleUtil;

public class HwmfText {
    private static final Logger LOG = LogManager.getLogger(HwmfText.class);
    private static final int MAX_RECORD_LENGTH = 1_000_000;

    /**
     * The META_SETTEXTCHAREXTRA record defines inter-character spacing for text justification in the
     * playback device context. Spacing is added to the white space between each character, including
     * break characters, when a line of justified text is output.
     */
    public static class WmfSetTextCharExtra implements HwmfRecord {

        /**
         * A 16-bit unsigned integer that defines the amount of extra space, in
         * logical units, to be added to each character. If the current mapping mode is not MM_TEXT,
         * this value is transformed and rounded to the nearest pixel. For details about setting the
         * mapping mode, see META_SETMAPMODE
         */
        private int charExtra;

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

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

        @Override
        public void draw(HwmfGraphics ctx) {

        }

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

    /**
     * The META_SETTEXTCOLOR record defines the text foreground color in the playback device context.
     */
    public static class WmfSetTextColor implements HwmfRecord {

        protected final HwmfColorRef colorRef = new HwmfColorRef();

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

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

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.getProperties().setTextColor(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_SETTEXTJUSTIFICATION record defines the amount of space to add to break characters
     * in a string of justified text.
     */
    public static class WmfSetTextJustification implements HwmfRecord {

        /**
         * A 16-bit unsigned integer that specifies the number of space characters in the line.
         */
        private int breakCount;

        /**
         * A 16-bit unsigned integer that specifies the total extra space, in logical
         * units, to be added to the line of text. If the current mapping mode is not MM_TEXT, the value
         * identified by the BreakExtra member is transformed and rounded to the nearest pixel. For
         * details about setting the mapping mode, see {@link WmfSetMapMode}.
         */
        private int breakExtra;

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

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

        @Override
        public void draw(HwmfGraphics ctx) {

        }

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

    /**
     * The META_TEXTOUT record outputs a character string at the specified location by using the font,
     * background color, and text color that are defined in the playback device context.
     */
    public static class WmfTextOut implements HwmfRecord, HwmfCharsetAware {
        /**
         * A 16-bit signed integer that defines the length of the string, in bytes, pointed to by String.
         */
        private int stringLength;
        /**
         * The size of this field MUST be a multiple of two. If StringLength is an odd
         * number, then this field MUST be of a size greater than or equal to StringLength + 1.
         * A variable-length string that specifies the text to be drawn.
         * The string does not need to be null-terminated, because StringLength specifies the
         * length of the string.
         * The string is written at the location specified by the XStart and YStart fields.
         */
        private byte[] rawTextBytes;

        protected Point2D reference = new Point2D.Double();

        protected Supplier<Charset> charsetProvider = () -> LocaleUtil.CHARSET_1252;

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

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            stringLength = leis.readShort();
            rawTextBytes = IOUtils.safelyAllocate(stringLength+(long)(stringLength&1), MAX_RECORD_LENGTH);
            leis.readFully(rawTextBytes);
            // A 16-bit signed integer that defines the vertical (y-axis) coordinate, in logical
            // units, of the point where drawing is to start.
            int yStart = leis.readShort();
            // A 16-bit signed integer that defines the horizontal (x-axis) coordinate, in
            // logical units, of the point where drawing is to start.
            int xStart = leis.readShort();
            reference.setLocation(xStart, yStart);
            return 3*LittleEndianConsts.SHORT_SIZE+rawTextBytes.length;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.setCharsetProvider(charsetProvider);
            ctx.drawString(getTextBytes(), stringLength, reference);
        }

        public String getText(Charset charset) {
            return new String(getTextBytes(), charset);
        }

        /**
         *
         * @return a copy of a trimmed byte array of rawTextBytes bytes.
         * This includes only the bytes from 0..stringLength.
         * This does not include the extra optional padding on the byte array.
         */
        private byte[] getTextBytes() {
            return IOUtils.safelyClone(rawTextBytes, 0, stringLength, MAX_RECORD_LENGTH);
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "text", () -> getText(charsetProvider.get()),
                "reference", () -> reference
            );
        }

        @Override
        public void setCharsetProvider(Supplier<Charset> provider) {
            charsetProvider = provider;
        }
    }

    @SuppressWarnings("unused")
    public static class WmfExtTextOutOptions implements GenericRecord {
        /**
         * Indicates that the background color that is defined in the playback device context
         * SHOULD be used to fill the rectangle.
         */
        private static final BitField ETO_OPAQUE = BitFieldFactory.getInstance(0x0002);

        /**
         * Indicates that the text SHOULD be clipped to the rectangle.
         */
        private static final BitField ETO_CLIPPED = BitFieldFactory.getInstance(0x0004);

        /**
         * Indicates that the string to be output SHOULD NOT require further processing
         * with respect to the placement of the characters, and an array of character
         * placement values SHOULD be provided. This character placement process is
         * useful for fonts in which diacritical characters affect character spacing.
         */
        private static final BitField ETO_GLYPH_INDEX = BitFieldFactory.getInstance(0x0010);

        /**
         * Indicates that the text MUST be laid out in right-to-left reading order, instead of
         * the default left-to-right order. This SHOULD be applied only when the font that is
         * defined in the playback device context is either Hebrew or Arabic.
         */
        private static final BitField ETO_RTLREADING = BitFieldFactory.getInstance(0x0080);

        /**
         * This bit indicates that the record does not specify a bounding rectangle for the
         * text output.
         */
        private static final BitField ETO_NO_RECT = BitFieldFactory.getInstance(0x0100);

        /**
         * This bit indicates that the codes for characters in an output text string are 8 bits,
         * derived from the low bytes of 16-bit Unicode UTF16-LE character codes, in which
         * the high byte is assumed to be 0.
         */
        private static final BitField ETO_SMALL_CHARS = BitFieldFactory.getInstance(0x0200);

        /**
         * Indicates that to display numbers, digits appropriate to the locale SHOULD be used.
         */
        private static final BitField ETO_NUMERICSLOCAL = BitFieldFactory.getInstance(0x0400);

        /**
         * Indicates that to display numbers, European digits SHOULD be used.
         */
        private static final BitField ETO_NUMERICSLATIN = BitFieldFactory.getInstance(0x0800);

        /**
         * This bit indicates that no special operating system processing for glyph placement
         * should be performed on right-to-left strings; that is, all glyph positioning
         * SHOULD be taken care of by drawing and state records in the metafile
         */
        private static final BitField ETO_IGNORELANGUAGE = BitFieldFactory.getInstance(0x1000);

        /**
         * Indicates that both horizontal and vertical character displacement values
         * SHOULD be provided.
         */
        private static final BitField ETO_PDY = BitFieldFactory.getInstance(0x2000);

        /** This bit is reserved and SHOULD NOT be used. */
        private static final BitField ETO_REVERSE_INDEX_MAP = BitFieldFactory.getInstance(0x10000);

        private static final int[] FLAGS_MASKS = {
            0x0002, 0x0004, 0x0010, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x10000
        };

        private static final String[] FLAGS_NAMES = {
            "OPAQUE", "CLIPPED", "GLYPH_INDEX", "RTLREADING", "NO_RECT", "SMALL_CHARS", "NUMERICSLOCAL",
            "NUMERICSLATIN", "IGNORELANGUAGE", "PDY", "REVERSE_INDEX_MAP"
        };

        protected int flags;

        public int init(LittleEndianInputStream leis) {
            flags = leis.readUShort();
            return LittleEndianConsts.SHORT_SIZE;
        }

        public boolean isOpaque() {
            return ETO_OPAQUE.isSet(flags);
        }

        public boolean isClipped() {
            return ETO_CLIPPED.isSet(flags);
        }

        public boolean isYDisplaced() {
            return ETO_PDY.isSet(flags);
        }

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

    /**
     * The META_EXTTEXTOUT record outputs text by using the font, background color, and text color that
     * are defined in the playback device context. Optionally, dimensions can be provided for clipping,
     * opaquing, or both.
     */
    public static class WmfExtTextOut implements HwmfRecord, HwmfCharsetAware {
        /**
         * The location, in logical units, where the text string is to be placed.
         */
        protected final Point2D reference = new Point2D.Double();

        /**
         * A 16-bit signed integer that defines the length of the string.
         */
        protected int stringLength;
        /**
         * A 16-bit unsigned integer that defines the use of the application-defined
         * rectangle. This member can be a combination of one or more values in the
         * ExtTextOutOptions Flags (ETO_*)
         */
        protected final WmfExtTextOutOptions options;
        /**
         * An optional 8-byte Rect Object (section 2.2.2.18) that defines the
         * dimensions, in logical coordinates, of a rectangle that is used for clipping, opaquing, or both.
         *
         * The corners are given in the order left, top, right, bottom.
         * Each value is a 16-bit signed integer that defines the coordinate, in logical coordinates, of
         * the upper-left corner of the rectangle
         */
        protected final Rectangle2D bounds = new Rectangle2D.Double();
        /**
         * A variable-length string that specifies the text to be drawn. The string does
         * not need to be null-terminated, because StringLength specifies the length of the string. If
         * the length is odd, an extra byte is placed after it so that the following member (optional Dx) is
         * aligned on a 16-bit boundary.
         */
        protected byte[] rawTextBytes;
        /**
         * An optional array of 16-bit signed integers that indicate the distance between
         * origins of adjacent character cells. For example, Dx[i] logical units separate the origins of
         * character cell i and character cell i + 1. If this field is present, there MUST be the same
         * number of values as there are characters in the string.
         */
        protected final List<Integer> dx = new ArrayList<>();

        protected Supplier<Charset> charsetProvider = () -> LocaleUtil.CHARSET_1252;

        public WmfExtTextOut() {
            this(new WmfExtTextOutOptions());
        }

        protected WmfExtTextOut(WmfExtTextOutOptions options) {
            this.options = options;
        }

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

        @Override
        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
            // -6 bytes of record function and length header
            final int remainingRecordSize = (int)(recordSize-6);

            int size = readPointS(leis, reference);

            stringLength = leis.readShort();
            size += LittleEndianConsts.SHORT_SIZE;
            size += options.init(leis);

            // Check if we have a rectangle
            if ((options.isOpaque() || options.isClipped()) && size+8<=remainingRecordSize) {
                // the bounding rectangle is optional and only read when options are given
                size += readRectS(leis, bounds);
            }

            rawTextBytes = IOUtils.safelyAllocate(stringLength+(long)(stringLength&1), MAX_RECORD_LENGTH);
            leis.readFully(rawTextBytes);
            size += rawTextBytes.length;

            if (size >= remainingRecordSize) {
                LOG.atInfo().log("META_EXTTEXTOUT doesn't contain character tracking info");
                return size;
            }

            int dxLen = Math.min(stringLength, (remainingRecordSize-size)/LittleEndianConsts.SHORT_SIZE);
            if (dxLen < stringLength) {
                LOG.atWarn().log("META_EXTTEXTOUT tracking info doesn't cover all characters");
            }

            for (int i=0; i<dxLen; i++) {
                dx.add((int)leis.readShort());
                size += LittleEndianConsts.SHORT_SIZE;
            }

            return size;
        }

        @Override
        public void draw(HwmfGraphics ctx) {
            ctx.setCharsetProvider(charsetProvider);
            ctx.drawString(rawTextBytes, stringLength, reference, null, bounds, options, dx, false);
        }

        public String getText(Charset charset) throws IOException {
            if (rawTextBytes == null) {
                return "";
            }
            String ret = new String(rawTextBytes, charset);
            return ret.substring(0, Math.min(ret.length(), stringLength));
        }

        public Point2D getReference() {
            return reference;
        }

        public Rectangle2D getBounds() {
            return bounds;
        }

        public WmfExtTextOutOptions getOptions() {
            return options;
        }

        protected boolean isUnicode() {
            return false;
        }

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

        private String getGenericText() {
            try {
                return getText(isUnicode() ? StandardCharsets.UTF_16LE : charsetProvider.get());
            } catch (IOException e) {
                return "";
            }
        }

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "reference", this::getReference,
                "bounds", this::getBounds,
                "options", this::getOptions,
                "text", this::getGenericText,
                "dx", () -> dx
            );
        }

        @Override
        public void setCharsetProvider(Supplier<Charset> provider) {
            charsetProvider = provider;
        }
    }

    public enum HwmfTextAlignment {
        LEFT,
        RIGHT,
        CENTER
    }

    public enum HwmfTextVerticalAlignment {
        TOP,
        BOTTOM,
        BASELINE
    }

    /**
     * The META_SETTEXTALIGN record defines text-alignment values in the playback device context.
     */
    public static class WmfSetTextAlign implements HwmfRecord {

        /**
         * The drawing position in the playback device context MUST be updated after each text
         * output call. It MUST be used as the reference point.<p>
         *
         * If the flag is not set, the option TA_NOUPDATECP is active, i.e. the drawing position
         * in the playback device context MUST NOT be updated after each text output call.
         * The reference point MUST be passed to the text output function.
         */
        @SuppressWarnings("unused")
        private static final BitField TA_UPDATECP = BitFieldFactory.getInstance(0x0001);

        /**
         * The text MUST be laid out in right-to-left reading order, instead of the default
         * left-to-right order. This SHOULD be applied only when the font that is defined in the
         * playback device context is either Hebrew or Arabic.
         */
        @SuppressWarnings("unused")
        private static final BitField TA_RTLREADING = BitFieldFactory.getInstance(0x0100);


        private static final BitField ALIGN_MASK = BitFieldFactory.getInstance(0x0006);

        /**
         * Flag TA_LEFT (0x0000):
         * The reference point MUST be on the left edge of the bounding rectangle,
         * if all bits of the align mask (latin mode) are unset.
         *
         * Flag VTA_TOP (0x0000):
         * The reference point MUST be on the top edge of the bounding rectangle,
         * if all bits of the valign mask are unset.
         */
        private static final int ALIGN_LEFT = 0;

        /**
         * Flag TA_RIGHT (0x0002):
         * The reference point MUST be on the right edge of the bounding rectangle.
         *
         * Flag VTA_BOTTOM (0x0002):
         * The reference point MUST be on the bottom edge of the bounding rectangle.
         */
        private static final int ALIGN_RIGHT = 1;

        /**
         * Flag TA_CENTER (0x0006) / VTA_CENTER (0x0006):
         * The reference point MUST be aligned horizontally with the center of the bounding
         * rectangle.
         */
        private static final int ALIGN_CENTER = 3;

        private static final BitField VALIGN_MASK = BitFieldFactory.getInstance(0x0018);

        /**
         * Flag TA_TOP (0x0000):
         * The reference point MUST be on the top edge of the bounding rectangle,
         * if all bits of the valign mask are unset.
         *
         * Flag VTA_RIGHT (0x0000):
         * The reference point MUST be on the right edge of the bounding rectangle,
         * if all bits of the align mask (asian mode) are unset.
         */
        private static final int VALIGN_TOP = 0;

        /**
         * Flag TA_BOTTOM (0x0008):
         * The reference point MUST be on the bottom edge of the bounding rectangle.
         *
         * Flag VTA_LEFT (0x0008):
         * The reference point MUST be on the left edge of the bounding rectangle.
         */
        private static final int VALIGN_BOTTOM = 1;

        /**
         * Flag TA_BASELINE (0x0018) / VTA_BASELINE (0x0018):
         * The reference point MUST be on the baseline of the text.
         */
        private static final int VALIGN_BASELINE = 3;

        /**
         * A 16-bit unsigned integer that defines text alignment.
         * This value MUST be a combination of one or more TextAlignmentMode Flags
         * for text with a horizontal baseline, and VerticalTextAlignmentMode Flags
         * for text with a vertical baseline.
         */
        protected int textAlignmentMode;

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

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

        @Override
        public void draw(HwmfGraphics ctx) {
            HwmfDrawProperties props = ctx.getProperties();
            props.setTextAlignLatin(getAlignLatin());
            props.setTextVAlignLatin(getVAlignLatin());
            props.setTextAlignAsian(getAlignAsian());
            props.setTextVAlignAsian(getVAlignAsian());
        }

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

        @Override
        public Map<String, Supplier<?>> getGenericProperties() {
            return GenericRecordUtil.getGenericProperties(
                "align", this::getAlignLatin,
                "valign", this::getVAlignLatin,
                "alignAsian", this::getAlignAsian,
                "valignAsian", this::getVAlignAsian
            );
        }

        private HwmfTextAlignment getAlignLatin() {
            switch (ALIGN_MASK.getValue(textAlignmentMode)) {
                default:
                case ALIGN_LEFT:
                    return HwmfTextAlignment.LEFT;
                case ALIGN_CENTER:
                    return HwmfTextAlignment.CENTER;
                case ALIGN_RIGHT:
                    return HwmfTextAlignment.RIGHT;
            }
        }

        private HwmfTextVerticalAlignment getVAlignLatin() {
            switch (VALIGN_MASK.getValue(textAlignmentMode)) {
                default:
                case VALIGN_TOP:
                    return HwmfTextVerticalAlignment.TOP;
                case VALIGN_BASELINE:
                    return HwmfTextVerticalAlignment.BASELINE;
                case VALIGN_BOTTOM:
                    return HwmfTextVerticalAlignment.BOTTOM;
            }
        }

        private HwmfTextAlignment getAlignAsian() {
            switch (getVAlignLatin()) {
                default:
                case TOP:
                    return HwmfTextAlignment.RIGHT;
                case BASELINE:
                    return HwmfTextAlignment.CENTER;
                case BOTTOM:
                    return HwmfTextAlignment.LEFT;
            }
        }

        private HwmfTextVerticalAlignment getVAlignAsian() {
            switch (getAlignLatin()) {
                default:
                case LEFT:
                    return HwmfTextVerticalAlignment.TOP;
                case CENTER:
                    return HwmfTextVerticalAlignment.BASELINE;
                case RIGHT:
                    return HwmfTextVerticalAlignment.BOTTOM;
            }
        }
    }

    public static class WmfCreateFontIndirect implements HwmfRecord, HwmfObjectTableEntry {
        protected final HwmfFont font;

        public WmfCreateFontIndirect() {
            this(new HwmfFont());
        }

        protected WmfCreateFontIndirect(HwmfFont font) {
            this.font = font;
        }

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

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

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

        @Override
        public void applyObject(HwmfGraphics ctx) {
            ctx.getProperties().setFont(font);
        }

        public HwmfFont getFont() {
            return font;
        }

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

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