/*
 * 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.render.pdf.pdfbox;

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

import org.apache.commons.io.output.CountingOutputStream;

import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFObject;
import org.apache.fop.pdf.PDFText;

/**
 * Special PDF object for strings that goes beyond FOP's {@link PDFText} class.
 */
public class PDFString extends PDFObject {

    private String text;
    private byte[] binary;

    /**
     * Creates a new String.
     * @param text the text
     */
    public PDFString(String text) {
        this.text = text;
    }

    /**
     * Creates a new String.
     * @param data the text data as byte array
     */
    public PDFString(byte[] data) {
        this.binary = data.clone();
    }

    /**
     * Returns the string as a Unicode string.
     * @return the string
     */
    public String getString() {
        if (this.text == null) {
            String encoding = "ISO-8859-1";
            int start = 0;
            if (this.binary.length > 2) {
                if (this.binary[0] == (byte)0xFF && this.binary[1] == (byte)0xFE) {
                    encoding = "UTF-16LE";
                    start = 2;
                } else if (this.binary[0] == (byte)0xFE && this.binary[1] == (byte)0xFF) {
                    encoding = "UTF-16BE";
                    start = 2;
                }
            }
            try {
                this.text = new String(this.binary, start, this.binary.length - start, encoding);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("Incompatible JVM: " + e.getMessage());
            }
        }
        return this.text;
    }

    /**
     * Returns the string as binary data.
     * @return the binary representation
     */
    public byte[] getBinary() {
        if (this.binary == null) {
            boolean unicode16 = false;
            char[] chars = this.text.toCharArray();
            int length = chars.length;
            for (int i = 0; i < length; i++) {
                if (chars[i] > 255) {
                    unicode16 = true;
                    break;
                }
            }
            try {
                byte[] binary;
                if (unicode16) {
                    byte[] data = this.text.getBytes("UTF-16BE");
                    binary = new byte[data.length + 2];
                    binary[0] = (byte)0xFE;
                    binary[1] = (byte)0xFF;
                    System.arraycopy(data, 0, binary, 2, data.length);
                } else {
                    byte[] data = this.text.getBytes("ISO-8859-1");
                    binary = new byte[data.length];
                    System.arraycopy(data, 0, binary, 0, data.length);
                }
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("Incompatible JVM: " + e.getMessage());
            }
        }
        if (binary == null) {
            return new byte[0];
        }
        return this.binary.clone();
    }

    @Override
    public int output(OutputStream stream) throws IOException {
        CountingOutputStream cout = new CountingOutputStream(stream);
        PDFDocument.flushTextBuffer(new StringBuilder(PDFText.escapeText(getString())), cout);
        return cout.getCount();
    }

    /**
     * Indicates whether the given binary data contains only US-ASCII characters.
     * @param data the binary data
     * @return true if only US-ASCII data is found
     */
    public static boolean isUSASCII(byte[] data) {
        for (int i = 0, c = data.length; i < c; i++) {
            if ((data[i] & 0xFF) >= 128) {
                return false;
            }
        }
        return true;
    }
}
