package com.jscape.util.io.primitive;

import com.jscape.util.EndianBits;
import com.jscape.util.IOTools;
import com.jscape.util.io.DataCodec;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import static com.jscape.util.Parameters.assertLesserOrEqual;

/**
 * @author Alex Usun
 */
public class ShortByteArrayCodec
        implements DataCodec<byte[]> {

    private final EndianBits bits;

    public static void writeValue(byte[] value, int offset, int length, EndianBits bits, OutputStream out)
            throws IOException {
        assertLesserOrEqual(length, 65536, "Bad data length.");
        ShortCodec.writeValue((short) length, bits, out);
        out.write(value, offset, length);
    }

    public static void writeValue(byte[] value, EndianBits bits, OutputStream out)
            throws IOException {
        writeValue(value, 0, value.length, bits, out);
    }

    public static void writeBigEndianValue(byte[] value, int offset, int length, OutputStream out)
            throws IOException {
        assertLesserOrEqual(length, 65536, "Bad data length.");
        ShortCodec.writeBigEndianValue((short) length, out);
        out.write(value, offset, length);
    }

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

    public static void writeLittleEndianValue(byte[] value, int offset, int length, OutputStream out)
            throws IOException {
        assertLesserOrEqual(length, 65536, "Bad data length.");
        ShortCodec.writeLittleEndianValue((short) length, out);
        out.write(value, offset, length);
    }

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

    public static byte[] readValue(EndianBits bits, InputStream in)
            throws IOException {
        int length = ShortCodec.readValue(bits, in) & 0xFFFF;
        return IOTools.read(new byte[length], in);
    }

    public static byte[] readBigEndianValue(InputStream in)
            throws IOException {
        int length = ShortCodec.readBigEndianValue(in) & 0xFFFF;
        return IOTools.read(new byte[length], in);
    }

    public static byte[] readLittleEndianValue(InputStream in)
            throws IOException {
        int length = ShortCodec.readLittleEndianValue(in) & 0xFFFF;
        return IOTools.read(new byte[length], in);
    }

    public ShortByteArrayCodec(EndianBits bits) {
        this.bits = bits;
    }

    public void write(byte[] data, OutputStream out)
            throws IOException {
        writeValue(data, this.bits, out);
    }

    public byte[] read(InputStream in)
            throws IOException {
        return readValue(this.bits, in);
    }

}
