// Path: BiliLiveLib/src/main/java/charlie/bililivelib/I18n.java
// public class I18n {
//     public static final String BUNDLE_NAME = "BiliLiveLib";
//     private static Map<String, String> strings;
// 
//     static {
//         init();
//     }
// 
//     /**
//      * 重新依照当前Locale获取并填充本地化字符串。在切换Locale后调用。
//      */
//     public static void init() {
//         strings = new HashMap<>();
//         fillResourceBundle();
//     }
// 
//     private static void fillResourceBundle() {
//         ResourceBundle resourceBundle = ResourceBundle.getBundle(BUNDLE_NAME);
//         for (String key : resourceBundle.keySet()) {
//             strings.put(key, resourceBundle.getString(key));
//         }
//     }
// 
//     /**
//      * 获取给定Key的本地化文本。
//      * @param key 键
//      * @return 本地化文本
//      */
//     @Nls
//     public static String getString(@NonNls @NotNull String key) {
//         return strings.get(key);
//     }
// 
//     /**
//      * 获取基于给定Key的本地化格式化文本。
//      * @param key 指向格式化模式的键
//      * @param arguments 格式化文本的参数
//      * @return 本地化并格式化后的文本
//      */
//     @NotNull
//     public static String format(@NonNls @NotNull String key,
//                                 @NonNls @NotNull Object... arguments) {
//         return MessageFormat.format(strings.get(key), arguments);
//     }
// }
// 
// Path: BiliLiveLib/src/main/java/charlie/bililivelib/exceptions/BiliLiveException.java
// public class BiliLiveException extends Exception {
//     public BiliLiveException() {
//         super();
//     }
// 
//     public BiliLiveException(String message) {
//         super(message);
//     }
// 
//     public BiliLiveException(String message, Throwable cause) {
//         super(message, cause);
//     }
// }
// 
// Path: BiliLiveLib/src/main/java/charlie/bililivelib/internalutil/ByteArrayOperation.java
// @Contract(pure = true)
// public static int byteArrayToInt(@NotNull byte[] bytes) {
//     int value = 0;
//     //由高位到低位
//     for (int i = 0; i < 4; i++) {
//         int shift = (4 - 1 - i) * 8;
//         value += (bytes[i] & 0x000000FF) << shift;//往高位游
//     }
//     return value;
// }
// 
// Path: BiliLiveLib/src/main/java/charlie/bililivelib/internalutil/ByteArrayOperation.java
// @Contract(pure = true)
// public static short byteArrayToShort(@NotNull byte[] b) {
//     short s0 = (short) b[1];
//     short s1 = (short) b[0];
//     s1 <<= 8;
//     return (short) (s0 | s1);
// }


import charlie.bililivelib.I18n;
import charlie.bililivelib.exceptions.BiliLiveException;
import lombok.Getter;
import java.io.IOException;
import java.io.InputStream;
import static charlie.bililivelib.internalutil.ByteArrayOperation.byteArrayToInt;
import static charlie.bililivelib.internalutil.ByteArrayOperation.byteArrayToShort;

        readArray(inputStream, tempBuf, 4); // Magic and params
        int bodyLength = length - PACKET_HEADER_SIZE;
        if (bodyLength == 0) return;

        operationID -= 1; // I don't know what this means...

        operation = DanmakuReceivePacket.Operation.forID(operationID);

        body = new byte[bodyLength];
        readArray(inputStream, body, bodyLength);
    }

    private int readArray(InputStream stream, byte[] buffer, int length) throws IOException {
        if (length > buffer.length)
            throw new IOException("offset + length > buffer.length");
        int readLength = 0;

        while (readLength < length) {
            int available = stream.read(buffer, 0, length - readLength);
            if (available == 0)
                throw new IOException("available == 0");
            readLength += available;
        }
        return readLength;
        //return stream.read(buffer, 0, length);
    }

    private void checkValidProtocolVersion(short version) throws BiliLiveException {
        if (version != 1)
// Path: BiliLiveLib/src/main/java/charlie/bililivelib/I18n.java
// public class I18n {
//     public static final String BUNDLE_NAME = "BiliLiveLib";
//     private static Map<String, String> strings;
// 
//     static {
//         init();
//     }
// 
//     /**
//      * 重新依照当前Locale获取并填充本地化字符串。在切换Locale后调用。
//      */
//     public static void init() {
//         strings = new HashMap<>();
//         fillResourceBundle();
//     }
// 
//     private static void fillResourceBundle() {
//         ResourceBundle resourceBundle = ResourceBundle.getBundle(BUNDLE_NAME);
//         for (String key : resourceBundle.keySet()) {
//             strings.put(key, resourceBundle.getString(key));
//         }
//     }
// 
//     /**
//      * 获取给定Key的本地化文本。
//      * @param key 键
//      * @return 本地化文本
//      */
//     @Nls
//     public static String getString(@NonNls @NotNull String key) {
//         return strings.get(key);
//     }
// 
//     /**
//      * 获取基于给定Key的本地化格式化文本。
//      * @param key 指向格式化模式的键
//      * @param arguments 格式化文本的参数
//      * @return 本地化并格式化后的文本
//      */
//     @NotNull
//     public static String format(@NonNls @NotNull String key,
//                                 @NonNls @NotNull Object... arguments) {
//         return MessageFormat.format(strings.get(key), arguments);
//     }
// }
// 
// Path: BiliLiveLib/src/main/java/charlie/bililivelib/exceptions/BiliLiveException.java
// public class BiliLiveException extends Exception {
//     public BiliLiveException() {
//         super();
//     }
// 
//     public BiliLiveException(String message) {
//         super(message);
//     }
// 
//     public BiliLiveException(String message, Throwable cause) {
//         super(message, cause);
//     }
// }
// 
// Path: BiliLiveLib/src/main/java/charlie/bililivelib/internalutil/ByteArrayOperation.java
// @Contract(pure = true)
// public static int byteArrayToInt(@NotNull byte[] bytes) {
//     int value = 0;
//     //由高位到低位
//     for (int i = 0; i < 4; i++) {
//         int shift = (4 - 1 - i) * 8;
//         value += (bytes[i] & 0x000000FF) << shift;//往高位游
//     }
//     return value;
// }
// 
// Path: BiliLiveLib/src/main/java/charlie/bililivelib/internalutil/ByteArrayOperation.java
// @Contract(pure = true)
// public static short byteArrayToShort(@NotNull byte[] b) {
//     short s0 = (short) b[1];
//     short s1 = (short) b[0];
//     s1 <<= 8;
//     return (short) (s0 | s1);
// }


// Path: BiliLiveLib/src/main/java/charlie/bililivelib/danmaku/DanmakuReceivePacket.java
import charlie.bililivelib.I18n;
import charlie.bililivelib.exceptions.BiliLiveException;
import lombok.Getter;
import java.io.IOException;
import java.io.InputStream;
import static charlie.bililivelib.internalutil.ByteArrayOperation.byteArrayToInt;
import static charlie.bililivelib.internalutil.ByteArrayOperation.byteArrayToShort;


        readArray(inputStream, tempBuf, 4); // Magic and params
        int bodyLength = length - PACKET_HEADER_SIZE;
        if (bodyLength == 0) return;

        operationID -= 1; // I don't know what this means...

        operation = DanmakuReceivePacket.Operation.forID(operationID);

        body = new byte[bodyLength];
        readArray(inputStream, body, bodyLength);
    }

    private int readArray(InputStream stream, byte[] buffer, int length) throws IOException {
        if (length > buffer.length)
            throw new IOException("offset + length > buffer.length");
        int readLength = 0;

        while (readLength < length) {
            int available = stream.read(buffer, 0, length - readLength);
            if (available == 0)
                throw new IOException("available == 0");
            readLength += available;
        }
        return readLength;
        //return stream.read(buffer, 0, length);
    }

    private void checkValidProtocolVersion(short version) throws BiliLiveException {
        if (version != 1)
            throw new BiliLiveException(I18n.format("msg.danmaku_protocol_error"));