// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.v23.vom;

import io.v.v23.vdl.Kind;
import io.v.v23.vdl.VdlType;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

/**
 * Binary encoding and decoding routines.
 */
public final class BinaryUtil {
    /**
     * Every binary stream starts with this magic byte, to distinguish the binary encoding from
     * the JSON encoding. Note that every valid JSON encoding must start with an ASCII character,or
     * the BOM U+FEFF, and this magic byte is unambiguous regardless of the endianness of the JSON
     * encoding.
     */
    public static final byte BINARY_MAGIC_BYTE = (byte) 0x80;
    static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
    private static final String END_OF_STREAM_MESSAGE = "End of stream prematurely reached.";

    /**
     * Unsigned integers are the basis for all other primitive values. This is a two-state encoding.
     * If the number is less than 128 (0 through 0x7f), its value is written directly. Otherwise the
     * value is written in big-endian byte order preceded by the negated byte length.
     * Returns true iff the value is non-zero.
     */
    public static boolean encodeUint(OutputStream out, final long value) throws IOException {
        if ((value & 0x7f) == value) {
            out.write((byte) value);
            return value != 0;
        }
        int len = 0;
        while (((value >>> (len * 8)) | 0xff) != 0xff) {
            len++;
        }
        len++;
        out.write(-len);
        while (len > 0) {
            len--;
            out.write((byte) (value >>> (len * 8)));
        }
        return true;
    }

    public static boolean encodeUint(OutputStream out, final int value) throws IOException {
        return encodeUint(out, value & 0xffffffffL);
    }

    public static boolean encodeUint(OutputStream out, final short value) throws IOException {
        return encodeUint(out, value & 0xffffL);
    }

    public static long decodeUint(InputStream in) throws IOException {
        int firstByte = in.read();
        if (firstByte == -1) {
            // EOF.
            throw new CorruptVomStreamException(END_OF_STREAM_MESSAGE);
        }
        if ((firstByte & 0x7f) == firstByte) {
            return firstByte;
        }
        int len = -(byte) firstByte;
        if (len > 8) {
            throw new CorruptVomStreamException("Invalid long byte length");
        }
        long value = 0;
        while (len > 0) {
            len--;
            int nextByte = in.read();
            if (nextByte == -1) {
                throw new CorruptVomStreamException(END_OF_STREAM_MESSAGE);
            }
            value = (value << 8) | nextByte;
        }
        return value;
    }

    /**
     * Signed integers are encoded as unsigned integers, where the low bit says whether to
     * complement the other bits to recover the int.
     * Returns true iff the value is non-zero.
     */
    public static boolean encodeInt(OutputStream out, final long value) throws IOException {
        if (value < 0) {
            return encodeUint(out, ((~value) << 1) | 1);
        } else {
            return encodeUint(out, value << 1);
        }
    }

    public static long decodeInt(InputStream in) throws IOException {
        long uint = decodeUint(in);
        if ((uint & 1) == 1) {
            return ~(uint >>> 1);
        } else {
            return uint >>> 1;
        }
    }

    /**
     * Floating point numbers are encoded as byte-reversed ieee754.
     * Returns true iff the value is non-zero;
     */
    public static boolean encodeDouble(OutputStream out, final double value) throws IOException {
        return encodeUint(out, Long.reverseBytes(Double.doubleToLongBits(value)));
    }

    public static double decodeDouble(InputStream in) throws IOException {
        return Double.longBitsToDouble(Long.reverseBytes(decodeUint(in)));
    }

    /**
     * Booleans are encoded as a byte where 0 = false and anything else is true.
     * Returns the encoded value.
     */
    public static boolean encodeBoolean(OutputStream out, final boolean value) throws IOException {
        out.write(value ? 1 : 0);
        return value;
    }

    public static boolean decodeBoolean(InputStream in) throws IOException {
        int nextByte = in.read();
        if (nextByte == -1) {
            throw new CorruptVomStreamException(END_OF_STREAM_MESSAGE);
        }
        return nextByte != 0;
    }

    /**
     * Encodes an array of bytes as byte count followed by byte values.
     */
    public static void encodeBytes(OutputStream out, byte[] data) throws IOException {
        encodeUint(out, data.length);
        out.write(data);
    }

    public static byte[] decodeBytes(InputStream in, int len) throws IOException {
        if (len == 0) {
            return new byte[0];
        }
        byte[] bytes = new byte[len];
        if (in.read(bytes) != bytes.length) {
            throw new CorruptVomStreamException(END_OF_STREAM_MESSAGE);
        }
        return bytes;
    }

    /**
     * Returns true iff the kind of type is []byte or [N]byte.
     */
    public static boolean isBytes(VdlType type) {
        return (type.getKind() == Kind.ARRAY || type.getKind() == Kind.LIST)
                && type.getElem().getKind() == Kind.BYTE;
    }

    /**
     * Returns true iff the type is encoded with a top-level message length.
     */
    public static boolean hasBinaryMsgLen(VdlType type) {
        if (isBytes(type)) {
            return false;
        }

        switch (type.getKind()) {
            case ANY:
            case ARRAY:
            case COMPLEX64:
            case COMPLEX128:
            case LIST:
            case MAP:
            case OPTIONAL:
            case SET:
            case STRUCT:
            case UNION:
                return true;
            default:
                return false;
        }
    }

    /**
     * Converts a string to byte array, null string is treated as empty string.
     */
    public static byte[] getBytes(String value) {
        if (value == null) {
            value = "";
        }
        return value.getBytes(UTF8_CHARSET);
    }

    /**
     * Upper-cases the first character of a given string.
     */
    public static String firstCharToUpper(String str) {
        return Character.toUpperCase(str.charAt(0)) + str.substring(1);
    }

    /**
     * Lower-cases the first character in a string.
     */
    public static String firstCharToLower(String str) {
        return Character.toLowerCase(str.charAt(0)) + str.substring(1);
    }
}
