/**
 * 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.activemq.openwire.utils;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.UTFDataFormatException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.activemq.openwire.buffer.DataByteArrayInputStream;
import org.apache.activemq.openwire.buffer.DataByteArrayOutputStream;
import org.apache.activemq.openwire.buffer.UTF8Buffer;

/**
 * The fixed version of the UTF8 encoding function. Some older JVM's UTF8
 * encoding function breaks when handling large strings.
 */
public final class OpenWireMarshallingSupport {

    public static final byte NULL = 0;
    public static final byte BOOLEAN_TYPE = 1;
    public static final byte BYTE_TYPE = 2;
    public static final byte CHAR_TYPE = 3;
    public static final byte SHORT_TYPE = 4;
    public static final byte INTEGER_TYPE = 5;
    public static final byte LONG_TYPE = 6;
    public static final byte DOUBLE_TYPE = 7;
    public static final byte FLOAT_TYPE = 8;
    public static final byte STRING_TYPE = 9;
    public static final byte BYTE_ARRAY_TYPE = 10;
    public static final byte MAP_TYPE = 11;
    public static final byte LIST_TYPE = 12;
    public static final byte BIG_STRING_TYPE = 13;

    private OpenWireMarshallingSupport() {
    }

    public static void marshalPrimitiveMap(Map<String, Object> map, DataOutput out) throws IOException {
        if (map == null) {
            out.writeInt(-1);
        } else {
            out.writeInt(map.size());
            for (String name : map.keySet()) {
                out.writeUTF(name);
                Object value = map.get(name);
                marshalPrimitive(out, value);
            }
        }
    }

    public static Map<String, Object> unmarshalPrimitiveMap(DataInput in) throws IOException {
        return unmarshalPrimitiveMap(in, Integer.MAX_VALUE);
    }

    public static Map<String, Object> unmarshalPrimitiveMap(DataInput in, boolean force) throws IOException {
        return unmarshalPrimitiveMap(in, Integer.MAX_VALUE, force);
    }

    public static Map<String, Object> unmarshalPrimitiveMap(DataInput in, int maxPropertySize) throws IOException {
        return unmarshalPrimitiveMap(in, maxPropertySize, false);
    }

    /**
     * @param in
     * @return
     * @throws IOException
     * @throws IOException
     */
    public static Map<String, Object> unmarshalPrimitiveMap(DataInput in, int maxPropertySize, boolean force) throws IOException {
        int size = in.readInt();
        if (size > maxPropertySize) {
            throw new IOException("Primitive map is larger than the allowed size: " + size);
        }
        if (size < 0) {
            return null;
        } else {
            Map<String, Object> rc = new HashMap<String, Object>(size);
            for (int i = 0; i < size; i++) {
                String name = in.readUTF();
                rc.put(name, unmarshalPrimitive(in, force));
            }
            return rc;
        }
    }

    public static void marshalPrimitiveList(List<Object> list, DataOutput out) throws IOException {
        out.writeInt(list.size());
        for (Object element : list) {
            marshalPrimitive(out, element);
        }
    }

    public static List<Object> unmarshalPrimitiveList(DataInput in) throws IOException {
        return unmarshalPrimitiveList(in, false);
    }

    public static List<Object> unmarshalPrimitiveList(DataInput in, boolean force) throws IOException {
        int size = in.readInt();
        List<Object> answer = new ArrayList<Object>(size);
        while (size-- > 0) {
            answer.add(unmarshalPrimitive(in, force));
        }
        return answer;
    }

    @SuppressWarnings("unchecked")
    public static void marshalPrimitive(DataOutput out, Object value) throws IOException {
        if (value == null) {
            marshalNull(out);
        } else if (value.getClass() == Boolean.class) {
            marshalBoolean(out, ((Boolean) value).booleanValue());
        } else if (value.getClass() == Byte.class) {
            marshalByte(out, ((Byte) value).byteValue());
        } else if (value.getClass() == Character.class) {
            marshalChar(out, ((Character) value).charValue());
        } else if (value.getClass() == Short.class) {
            marshalShort(out, ((Short) value).shortValue());
        } else if (value.getClass() == Integer.class) {
            marshalInt(out, ((Integer) value).intValue());
        } else if (value.getClass() == Long.class) {
            marshalLong(out, ((Long) value).longValue());
        } else if (value.getClass() == Float.class) {
            marshalFloat(out, ((Float) value).floatValue());
        } else if (value.getClass() == Double.class) {
            marshalDouble(out, ((Double) value).doubleValue());
        } else if (value.getClass() == byte[].class) {
            marshalByteArray(out, (byte[]) value);
        } else if (value.getClass() == String.class) {
            marshalString(out, (String) value);
        } else if (value.getClass() == UTF8Buffer.class) {
            marshalString(out, value.toString());
        } else if (value instanceof Map) {
            out.writeByte(MAP_TYPE);
            marshalPrimitiveMap((Map<String, Object>) value, out);
        } else if (value instanceof List) {
            out.writeByte(LIST_TYPE);
            marshalPrimitiveList((List<Object>) value, out);
        } else {
            throw new IOException("Object is not a primitive: " + value);
        }
    }

    public static Object unmarshalPrimitive(DataInput in) throws IOException {
        return unmarshalPrimitive(in, false);
    }

    public static Object unmarshalPrimitive(DataInput in, boolean force) throws IOException {
        Object value = null;
        byte type = in.readByte();
        switch (type) {
            case BYTE_TYPE:
                value = Byte.valueOf(in.readByte());
                break;
            case BOOLEAN_TYPE:
                value = in.readBoolean() ? Boolean.TRUE : Boolean.FALSE;
                break;
            case CHAR_TYPE:
                value = Character.valueOf(in.readChar());
                break;
            case SHORT_TYPE:
                value = Short.valueOf(in.readShort());
                break;
            case INTEGER_TYPE:
                value = Integer.valueOf(in.readInt());
                break;
            case LONG_TYPE:
                value = Long.valueOf(in.readLong());
                break;
            case FLOAT_TYPE:
                value = new Float(in.readFloat());
                break;
            case DOUBLE_TYPE:
                value = new Double(in.readDouble());
                break;
            case BYTE_ARRAY_TYPE:
                value = new byte[in.readInt()];
                in.readFully((byte[]) value);
                break;
            case STRING_TYPE:
                if (force) {
                    value = in.readUTF();
                } else {
                    value = readUTF(in, in.readUnsignedShort());
                }
                break;
            case BIG_STRING_TYPE: {
                if (force) {
                    value = readUTF8(in);
                } else {
                    value = readUTF(in, in.readInt());
                }
                break;
            }
            case MAP_TYPE:
                value = unmarshalPrimitiveMap(in, true);
                break;
            case LIST_TYPE:
                value = unmarshalPrimitiveList(in, true);
                break;
            case NULL:
                value = null;
                break;
            default:
                throw new IOException("Unknown primitive type: " + type);
        }
        return value;
    }

    public static UTF8Buffer readUTF(DataInput in, int length) throws IOException {
        byte data[] = new byte[length];
        in.readFully(data);
        return new UTF8Buffer(data);
    }

    public static void marshalNull(DataOutput out) throws IOException {
        out.writeByte(NULL);
    }

    public static void marshalBoolean(DataOutput out, boolean value) throws IOException {
        out.writeByte(BOOLEAN_TYPE);
        out.writeBoolean(value);
    }

    public static void marshalByte(DataOutput out, byte value) throws IOException {
        out.writeByte(BYTE_TYPE);
        out.writeByte(value);
    }

    public static void marshalChar(DataOutput out, char value) throws IOException {
        out.writeByte(CHAR_TYPE);
        out.writeChar(value);
    }

    public static void marshalShort(DataOutput out, short value) throws IOException {
        out.writeByte(SHORT_TYPE);
        out.writeShort(value);
    }

    public static void marshalInt(DataOutput out, int value) throws IOException {
        out.writeByte(INTEGER_TYPE);
        out.writeInt(value);
    }

    public static void marshalLong(DataOutput out, long value) throws IOException {
        out.writeByte(LONG_TYPE);
        out.writeLong(value);
    }

    public static void marshalFloat(DataOutput out, float value) throws IOException {
        out.writeByte(FLOAT_TYPE);
        out.writeFloat(value);
    }

    public static void marshalDouble(DataOutput out, double value) throws IOException {
        out.writeByte(DOUBLE_TYPE);
        out.writeDouble(value);
    }

    public static void marshalByteArray(DataOutput out, byte[] value) throws IOException {
        marshalByteArray(out, value, 0, value.length);
    }

    public static void marshalByteArray(DataOutput out, byte[] value, int offset, int length) throws IOException {
        out.writeByte(BYTE_ARRAY_TYPE);
        out.writeInt(length);
        out.write(value, offset, length);
    }

    public static void marshalString(DataOutput out, String s) throws IOException {
        // If it's too big, out.writeUTF may not able able to write it out.
        if (s.length() < Short.MAX_VALUE / 4) {
            out.writeByte(STRING_TYPE);
            out.writeUTF(s);
        } else {
            out.writeByte(BIG_STRING_TYPE);
            writeUTF8(out, s);
        }
    }

    public static void writeUTF8(DataOutput dataOut, String text) throws IOException {
        if (text != null) {
            int strlen = text.length();
            int utflen = 0;
            char[] charr = new char[strlen];
            int c = 0;
            int count = 0;

            text.getChars(0, strlen, charr, 0);

            for (int i = 0; i < strlen; i++) {
                c = charr[i];
                if ((c >= 0x0001) && (c <= 0x007F)) {
                    utflen++;
                } else if (c > 0x07FF) {
                    utflen += 3;
                } else {
                    utflen += 2;
                }
            }
            // TODO diff: Sun code - removed
            byte[] bytearr = new byte[utflen + 4]; // TODO diff: Sun code
            bytearr[count++] = (byte) ((utflen >>> 24) & 0xFF); // TODO diff:
            // Sun code
            bytearr[count++] = (byte) ((utflen >>> 16) & 0xFF); // TODO diff:
            // Sun code
            bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
            bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
            for (int i = 0; i < strlen; i++) {
                c = charr[i];
                if ((c >= 0x0001) && (c <= 0x007F)) {
                    bytearr[count++] = (byte) c;
                } else if (c > 0x07FF) {
                    bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
                    bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
                    bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
                } else {
                    bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
                    bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
                }
            }
            dataOut.write(bytearr);

        } else {
            dataOut.writeInt(-1);
        }
    }

    public static String readUTF8(DataInput dataIn) throws IOException {
        int utflen = dataIn.readInt(); // TODO diff: Sun code
        if (utflen > -1) {
            StringBuffer str = new StringBuffer(utflen);
            byte bytearr[] = new byte[utflen];
            int c;
            int char2;
            int char3;
            int count = 0;

            dataIn.readFully(bytearr, 0, utflen);

            while (count < utflen) {
                c = bytearr[count] & 0xff;
                switch (c >> 4) {
                    case 0:
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                        /* 0xxxxxxx */
                        count++;
                        str.append((char) c);
                        break;
                    case 12:
                    case 13:
                        /* 110x xxxx 10xx xxxx */
                        count += 2;
                        if (count > utflen) {
                            throw new UTFDataFormatException();
                        }
                        char2 = bytearr[count - 1];
                        if ((char2 & 0xC0) != 0x80) {
                            throw new UTFDataFormatException();
                        }
                        str.append((char) (((c & 0x1F) << 6) | (char2 & 0x3F)));
                        break;
                    case 14:
                        /* 1110 xxxx 10xx xxxx 10xx xxxx */
                        count += 3;
                        if (count > utflen) {
                            throw new UTFDataFormatException();
                        }
                        char2 = bytearr[count - 2]; // TODO diff: Sun code
                        char3 = bytearr[count - 1]; // TODO diff: Sun code
                        if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
                            throw new UTFDataFormatException();
                        }
                        str.append((char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)));
                        break;
                    default:
                        /* 10xx xxxx, 1111 xxxx */
                        throw new UTFDataFormatException();
                }
            }
            // The number of chars produced may be less than utflen
            return new String(str);
        } else {
            return null;
        }
    }

    public static String propertiesToString(Properties props) throws IOException {
        String result = "";
        if (props != null) {
            DataByteArrayOutputStream dataOut = new DataByteArrayOutputStream();
            props.store(dataOut, "");
            result = new String(dataOut.getData(), 0, dataOut.size());
            dataOut.close();
        }
        return result;
    }

    public static Properties stringToProperties(String str) throws IOException {
        Properties result = new Properties();
        if (str != null && str.length() > 0) {
            DataByteArrayInputStream dataIn = new DataByteArrayInputStream(str.getBytes());
            result.load(dataIn);
            dataIn.close();
        }
        return result;
    }

    public static String truncate64(String text) {
        if (text.length() > 63) {
            text = text.substring(0, 45) + "..." + text.substring(text.length() - 12);
        }
        return text;
    }
}
