/*
 * 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.
 */

/* $Id$ */

package org.apache.fop.afp.modca;

import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.fop.afp.AFPLineDataInfo;
import org.apache.fop.afp.AFPTextDataInfo;
import org.apache.fop.afp.util.BinaryUtils;

/**
 * Presentation text data contains the graphic characters and the control
 * sequences necessary to position the characters within the object space. The
 * data consists of: - graphic characters to be presented - control sequences
 * that position them - modal control sequences that adjust the positions by
 * small amounts - other functions causing text to be presented with differences
 * in appearance.
 *
 * The graphic characters are expected to conform to a coded font representation
 * so that they can be translated from the code point in the object data to the
 * character in the coded font. The units of measure for linear displacements
 * are derived from the PresentationTextDescriptor or from the hierarchical
 * defaults.
 *
 * In addition to graphic character code points, Presentation Text data can
 * contain embedded control sequences. These are strings of two or more bytes
 * which signal an alternate mode of processing for the content of the current
 * Presentation Text data.
 *
 */
public class PresentationTextData extends AbstractAFPObject {

    /** the maximum size of the presentation text data.*/
    private static final int MAX_SIZE = 8192;

    /** the AFP data relating to this presentation text data. */
    private final ByteArrayOutputStream baos = new ByteArrayOutputStream();

    /** the current x coordinate. */
    private int currentX = -1;

    /** the current y cooridnate */
    private int currentY = -1;

    /** the current font */
    private String currentFont = "";

    /** the current orientation */
    private int currentOrientation = 0;

    /** the current color */
    private Color currentColor = new Color(0, 0, 0);

    /** the current variable space increment */
    private int currentVariableSpaceCharacterIncrement = 0;

    /** the current inter character adjustment */
    private int currentInterCharacterAdjustment = 0;

    /**
     * Default constructor for the PresentationTextData.
     */
    public PresentationTextData() {
        this(false);
    }

    /**
     * Constructor for the PresentationTextData, the boolean flag indicate
     * whether the control sequence prefix should be set to indicate the start
     * of a new control sequence.
     *
     * @param controlInd
     *            The control sequence indicator.
     */
    public PresentationTextData(boolean controlInd) {
        final byte[] data = {
                0x5A, // Structured field identifier
                0x00, // Record length byte 1
                0x00, // Record length byte 2
                SF_CLASS, // PresentationTextData identifier byte 1
                Type.DATA, // PresentationTextData identifier byte 2
                Category.PRESENTATION_TEXT, // PresentationTextData identifier byte 3
                0x00, // Flag
                0x00, // Reserved
                0x00, // Reserved
        };
        baos.write(data, 0, 9);

        if (controlInd) {
            baos.write(new byte[] {0x2B, (byte) 0xD3}, 0, 2);
        }
    }

    /**
     * The Set Coded Font Local control sequence activates a coded font and
     * specifies the character attributes to be used. This is a modal control
     * sequence.
     *
     * @param font
     *            The font local identifier.
     * @param afpdata
     *            The output stream to which data should be written.
     */
    private void setCodedFont(byte font, ByteArrayOutputStream afpdata) {
        // Avoid unnecessary specification of the font
        if (String.valueOf(font).equals(currentFont)) {
            return;
        } else {
            currentFont = String.valueOf(font);
        }

        afpdata.write(new byte[] {0x03, (byte) 0xF1, font}, 0, 3);
    }

    /**
     * Establishes the current presentation position on the baseline at a new
     * I-axis coordinate, which is a specified number of measurement units from
     * the B-axis. There is no change to the current B-axis coordinate.
     *
     * @param coordinate
     *            The coordinate for the inline move.
     * @param afpdata
     *            The output stream to which data should be written.
     */
    private void absoluteMoveInline(int coordinate,
            ByteArrayOutputStream afpdata) {
        byte[] b = BinaryUtils.convert(coordinate, 2);
        afpdata.write(new byte[] {0x04, (byte) 0xC7, b[0], b[1]}, 0, 4);
        currentX = coordinate;
    }

    /**
     * Establishes the baseline and the current presentation position at a new
     * B-axis coordinate, which is a specified number of measurement units from
     * the I-axis. There is no change to the current I-axis coordinate.
     *
     * @param coordinate
     *            The coordinate for the baseline move.
     * @param afpdata
     *            The output stream to which data should be written.
     */
    private void absoluteMoveBaseline(int coordinate,
            ByteArrayOutputStream afpdata) {
        byte[] b = BinaryUtils.convert(coordinate, 2);
        afpdata.write(new byte[] {0x04, (byte) 0xD3, b[0], b[1]}, 0, 4);
        currentY = coordinate;
    }

    private static final int TRANSPARENT_MAX_SIZE = 253;

    /**
     * The Transparent Data control sequence contains a sequence of code points
     * that are presented without a scan for embedded control sequences.
     *
     * @param data
     *            The text data to add.
     * @param afpdata
     *            The output stream to which data should be written.
     */
    private void addTransparentData(byte[] data, ByteArrayOutputStream afpdata) {
        // Calculate the length
        int l = data.length + 2;
        if (l > 255) {
            // Check that we are not exceeding the maximum length
            throw new IllegalArgumentException(
                    "Transparent data is longer than " + TRANSPARENT_MAX_SIZE + " bytes: " + data);
        }
        afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB},
                0, 2);
        afpdata.write(data, 0, data.length);
    }

    /**
     * Draws a line of specified length and specified width in the B-direction
     * from the current presentation position. The location of the current
     * presentation position is unchanged.
     *
     * @param length
     *            The length of the rule.
     * @param width
     *            The width of the rule.
     * @param afpdata
     *            The output stream to which data should be written.
     */
    private void drawBaxisRule(int length, int width,
            ByteArrayOutputStream afpdata) {
        afpdata.write(new byte[] {
                0x07, // Length
                (byte) 0xE7, // Type
        }, 0, 2);
        // Rule length
        byte[] data1 = BinaryUtils.shortToByteArray((short) length);
        afpdata.write(data1, 0, data1.length);
        // Rule width
        byte[] data2 = BinaryUtils.shortToByteArray((short) width);
        afpdata.write(data2, 0, data2.length);
        // Rule width fraction
        afpdata.write(0x00);
    }

    /**
     * Draws a line of specified length and specified width in the I-direction
     * from the current presentation position. The location of the current
     * presentation position is unchanged.
     *
     * @param length
     *            The length of the rule.
     * @param width
     *            The width of the rule.
     * @param afpdata
     *            The output stream to which data should be written.
     */
    private void drawIaxisRule(int length, int width,
            ByteArrayOutputStream afpdata) {
        afpdata.write(new byte[] {
                0x07, // Length
                (byte) 0xE5, // Type
        }, 0, 2);
        // Rule length
        byte[] data1 = BinaryUtils.shortToByteArray((short) length);
        afpdata.write(data1, 0, data1.length);
        // Rule width
        byte[] data2 = BinaryUtils.shortToByteArray((short) width);
        afpdata.write(data2, 0, data2.length);
        // Rule width fraction
        afpdata.write(0x00);
    }

    /**
     * Create the presentation text data for the byte array of data.
     *
     * @param textDataInfo
     *            the afp text data
     * @throws MaximumSizeExceededException
     *            thrown if the maximum number of text data is exceeded
     * @throws UnsupportedEncodingException
     *            thrown if character encoding is not supported
     */
    public void createTextData(AFPTextDataInfo textDataInfo)
            throws MaximumSizeExceededException, UnsupportedEncodingException {

        ByteArrayOutputStream afpdata = new ByteArrayOutputStream();

        int rotation = textDataInfo.getRotation();
        if (currentOrientation != rotation) {
            setTextOrientation(rotation, afpdata);
            currentOrientation = rotation;
            currentX = -1;
            currentY = -1;
        }

        // Avoid unnecessary specification of the Y coordinate
        int y = textDataInfo.getY();
        if (currentY != y) {
            absoluteMoveBaseline(y, afpdata);
            currentX = -1;
        }

        // Avoid unnecessary specification of the X coordinate
        int x = textDataInfo.getX();
        if (currentX != x) {
            absoluteMoveInline(x, afpdata);
        }

        // Avoid unnecessary specification of the variable space increment
        if (textDataInfo.getVariableSpaceCharacterIncrement()
                != currentVariableSpaceCharacterIncrement) {
            setVariableSpaceCharacterIncrement(textDataInfo
                    .getVariableSpaceCharacterIncrement(), afpdata);
            currentVariableSpaceCharacterIncrement = textDataInfo
                    .getVariableSpaceCharacterIncrement();
        }

        // Avoid unnecessary specification of the inter character adjustment
        if (textDataInfo.getInterCharacterAdjustment() != currentInterCharacterAdjustment) {
            setInterCharacterAdjustment(textDataInfo.getInterCharacterAdjustment(),
                    afpdata);
            currentInterCharacterAdjustment = textDataInfo
                    .getInterCharacterAdjustment();
        }

        // Avoid unnecessary specification of the text color
        if (!textDataInfo.getColor().equals(currentColor)) {
            setExtendedTextColor(textDataInfo.getColor(), afpdata);
            currentColor = textDataInfo.getColor();
        }

        setCodedFont(BinaryUtils.convert(textDataInfo.getFontReference())[0],
                afpdata);

        // Add transparent data
        String textString = textDataInfo.getString();
        String encoding = textDataInfo.getEncoding();
        byte[] data = textString.getBytes(encoding);
        if (data.length <= TRANSPARENT_MAX_SIZE) {
            addTransparentData(data, afpdata);
        } else {
            // data size greater than TRANSPARENT_MAX_SIZE so slice
            int numTransData = data.length / TRANSPARENT_MAX_SIZE;
            byte[] buff = new byte[TRANSPARENT_MAX_SIZE];
            int currIndex = 0;
            for (int transDataCnt = 0; transDataCnt < numTransData; transDataCnt++) {
                currIndex = transDataCnt * TRANSPARENT_MAX_SIZE;
                System.arraycopy(data, currIndex, buff, 0, TRANSPARENT_MAX_SIZE);
                addTransparentData(buff, afpdata);
            }
            int remainingTransData = data.length / TRANSPARENT_MAX_SIZE;
            buff = new byte[remainingTransData];
            System.arraycopy(data, currIndex, buff, 0, remainingTransData);
            addTransparentData(buff, afpdata);
        }
        currentX = -1;

        int dataSize = afpdata.size();

        if (baos.size() + dataSize > MAX_SIZE) {
            currentX = -1;
            currentY = -1;
            throw new MaximumSizeExceededException();
        }

        byte[] outputdata = afpdata.toByteArray();
        baos.write(outputdata, 0, outputdata.length);
    }

    private int ensurePositive(int value) {
        if (value < 0) {
            return 0;
        }
        return value;
    }

    /**
     * Drawing of lines using the starting and ending coordinates, thickness and
     * colour arguments.
     *
     * @param lineDataInfo the line data information.
     * @throws MaximumSizeExceededException
     *            thrown if the maximum number of line data has been exceeded
     */
    public void createLineData(AFPLineDataInfo lineDataInfo) throws MaximumSizeExceededException {

        ByteArrayOutputStream afpdata = new ByteArrayOutputStream();

        int orientation = lineDataInfo.getRotation();
        if (currentOrientation != orientation) {
            setTextOrientation(orientation, afpdata);
            currentOrientation = orientation;
        }

        // Avoid unnecessary specification of the Y coordinate
        int y1 = ensurePositive(lineDataInfo.getY1());
        if (y1 != currentY) {
            absoluteMoveBaseline(y1, afpdata);
        }

        // Avoid unnecessary specification of the X coordinate
        int x1 = ensurePositive(lineDataInfo.getX1());
        if (x1 != currentX) {
            absoluteMoveInline(x1, afpdata);
        }

        Color color = lineDataInfo.getColor();
        if (!color.equals(currentColor)) {
            setExtendedTextColor(color, afpdata);
            currentColor = color;
        }

        int x2 = ensurePositive(lineDataInfo.getX2());
        int y2 = ensurePositive(lineDataInfo.getY2());
        int thickness = lineDataInfo.getThickness();
        if (y1 == y2) {
            drawIaxisRule(x2 - x1, thickness, afpdata);
        } else if (x1 == x2) {
            drawBaxisRule(y2 - y1, thickness, afpdata);
        } else {
            log.error("Invalid axis rule unable to draw line");
            return;
        }

        int dataSize = afpdata.size();

        if (baos.size() + dataSize > MAX_SIZE) {
            currentX = -1;
            currentY = -1;
            throw new MaximumSizeExceededException();
        }

        byte[] outputdata = afpdata.toByteArray();
        baos.write(outputdata, 0, outputdata.length);
    }

    /**
     * The Set Text Orientation control sequence establishes the I-direction and
     * B-direction for the subsequent text. This is a modal control sequence.
     *
     * Semantics: This control sequence specifies the I-axis and B-axis
     * orientations with respect to the Xp-axis for the current Presentation
     * Text object. The orientations are rotational values expressed in degrees
     * and minutes.
     *
     * @param orientation
     *            The text orientation (0, 90, 180, 270).
     * @param os
     *            The output stream to which data should be written.
     */
    private void setTextOrientation(int orientation,
            ByteArrayOutputStream os) {
        os.write(new byte[] {0x06, (byte) 0xF7, }, 0, 2);
        switch (orientation) {
        case 90:
            os.write(0x2D);
            os.write(0x00);
            os.write(0x5A);
            os.write(0x00);
            break;
        case 180:
            os.write(0x5A);
            os.write(0x00);
            os.write(0x87);
            os.write(0x00);
            break;
        case 270:
            os.write(0x87);
            os.write(0x00);
            os.write(0x00);
            os.write(0x00);
            break;
        default:
            os.write(0x00);
            os.write(0x00);
            os.write(0x2D);
            os.write(0x00);
            break;
        }
    }

    /**
     * The Set Extended Text Color control sequence specifies a color value and
     * defines the color space and encoding for that value. The specified color
     * value is applied to foreground areas of the text presentation space. This
     * is a modal control sequence.
     *
     * @param col
     *            The color to be set.
     * @param os
     *            The output stream to which data should be written.
     */
    private void setExtendedTextColor(Color col, ByteArrayOutputStream os) {
        byte[] colorData = new byte[] {
            15, // Control sequence length
            (byte) 0x81, // Control sequence function type
            0x00, // Reserved; must be zero
            0x01, // Color space - 0x01 = RGB
            0x00, // Reserved; must be zero
            0x00, // Reserved; must be zero
            0x00, // Reserved; must be zero
            0x00, // Reserved; must be zero
            8, // Number of bits in component 1
            8, // Number of bits in component 2
            8, // Number of bits in component 3
            0, // Number of bits in component 4
            (byte) (col.getRed()), // Red intensity
            (byte) (col.getGreen()), // Green intensity
            (byte) (col.getBlue()), // Blue intensity
        };

        os.write(colorData, 0, colorData.length);
    }

    /**
     * //TODO This is a modal control sequence.
     *
     * @param incr
     *            The increment to be set.
     * @param os
     *            The output stream to which data should be written.
     */
    private void setVariableSpaceCharacterIncrement(int incr,
            ByteArrayOutputStream os) {
        byte[] b = BinaryUtils.convert(incr, 2);

        os.write(new byte[] {
                4, // Control sequence length
                (byte) 0xC5, // Control sequence function type
                b[0], b[1] },
                0, 4);
    }

    /**
     * //TODO This is a modal control sequence.
     *
     * @param incr
     *            The increment to be set.
     * @param os
     *            The output stream to which data should be written.
     */
    private void setInterCharacterAdjustment(int incr, ByteArrayOutputStream os) {
        byte[] b = BinaryUtils.convert(Math.abs(incr), 2);
        os.write(new byte[] {
                5, // Control sequence length
                (byte) 0xC3, // Control sequence function type
                b[0], b[1], (byte) (incr >= 0 ? 0 : 1) // Direction
                }, 0, 5);
    }

    /** {@inheritDoc} */
    public void writeToStream(OutputStream os) throws IOException {
        byte[] data = baos.toByteArray();
        byte[] size = BinaryUtils.convert(data.length - 1, 2);
        data[1] = size[0];
        data[2] = size[1];
        os.write(data);
    }

    /**
     * A control sequence is a sequence of bytes that specifies a control
     * function. A control sequence consists of a control sequence introducer
     * and zero or more parameters. The control sequence can extend multiple
     * presentation text data objects, but must eventually be terminated. This
     * method terminates the control sequence.
     *
     * @throws MaximumSizeExceededException
     *       thrown in the event that maximum size has been exceeded
     */
    public void endControlSequence() throws MaximumSizeExceededException {
        byte[] data = new byte[2];
        data[0] = 0x02;
        data[1] = (byte) 0xF8;
        if (data.length + baos.size() > MAX_SIZE) {
            throw new MaximumSizeExceededException();
        }
        baos.write(data, 0, data.length);
    }
}