// 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;
package charlie.bililivelib.danmaku;




/**
 * 用于从弹幕服务器发回的数据包。<br>
 * 数据包的结构如下:<br>
 * {@code +-----+-------+-----+--------+-------+----------+}<br>
 * {@code | LEN | MAGIC | UNK | OPCODE | B.LEN | --BODY-- |}<br>
 * {@code | -4- | X'0F' | -2- | --4--- | --4-- | Variable |}<br>
 * {@code +-----+-------+-----+--------+-------+----------+}<br>
 * - LEN:    数据包长度，包含自身长度，int类型;<br>
 * - MAGIC:  魔数，short类型，固定0x0F;<br>
 * - UNK:    未知参数，int类型;<br>
 * - OPCODE: 操作码，int类型。具体见{@link DanmakuReceivePacket.Operation};<br>
 * - B.LEN:  BODY的长度，int类型;<br>
 * - BODY:   数据包体，长度可变。
 *
 * @author Charlie Jiang
 * @since rv1
 */
@Getter
public final class DanmakuReceivePacket {
    private static final int PACKET_HEADER_SIZE = 16;

    private Operation operation = null;
    private byte[] body = null;

    /**
     * 对于指定输入流，读取并构造数据包结构。
     *
     * @param inputStream 输入流
     * @throws IOException       发生网络错误时抛出
     * @throws BiliLiveException 协议错误时抛出
     */
    public DanmakuReceivePacket(InputStream inputStream) throws IOException, BiliLiveException {
        byte[] tempBuf = new byte[4];
        readArray(inputStream, tempBuf, 4);
// 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;

package charlie.bililivelib.danmaku;




/**
 * 用于从弹幕服务器发回的数据包。<br>
 * 数据包的结构如下:<br>
 * {@code +-----+-------+-----+--------+-------+----------+}<br>
 * {@code | LEN | MAGIC | UNK | OPCODE | B.LEN | --BODY-- |}<br>
 * {@code | -4- | X'0F' | -2- | --4--- | --4-- | Variable |}<br>
 * {@code +-----+-------+-----+--------+-------+----------+}<br>
 * - LEN:    数据包长度，包含自身长度，int类型;<br>
 * - MAGIC:  魔数，short类型，固定0x0F;<br>
 * - UNK:    未知参数，int类型;<br>
 * - OPCODE: 操作码，int类型。具体见{@link DanmakuReceivePacket.Operation};<br>
 * - B.LEN:  BODY的长度，int类型;<br>
 * - BODY:   数据包体，长度可变。
 *
 * @author Charlie Jiang
 * @since rv1
 */
@Getter
public final class DanmakuReceivePacket {
    private static final int PACKET_HEADER_SIZE = 16;

    private Operation operation = null;
    private byte[] body = null;

    /**
     * 对于指定输入流，读取并构造数据包结构。
     *
     * @param inputStream 输入流
     * @throws IOException       发生网络错误时抛出
     * @throws BiliLiveException 协议错误时抛出
     */
    public DanmakuReceivePacket(InputStream inputStream) throws IOException, BiliLiveException {
        byte[] tempBuf = new byte[4];
        readArray(inputStream, tempBuf, 4);
        int length = byteArrayToInt(tempBuf);