content: package org.allaymc.server.datastruct.palette;
  
  import io.netty.buffer.ByteBuf;
  import io.netty.buffer.ByteBufAllocator;
  import io.netty.buffer.ByteBufInputStream;
  import io.netty.buffer.ByteBufUtil;
  import org.allaymc.server.datastruct.bitarray.BitArrayVersion;
  import org.cloudburstmc.nbt.NbtMap;
  import org.cloudburstmc.nbt.NbtUtils;
  import org.junit.jupiter.api.Test;
  
  import java.io.IOException;
  
  import static org.junit.jupiter.api.Assertions.*;
  
  /**
   * @author daoge_cmd
   */
  class PaletteTest {
  
      @Test
      void testGeneric() {
          var e0 = new Entry(0);
          var palette = new Palette<>(e0, BitArrayVersion.V0);
          assertEquals(e0, palette.get(0));
  
          var e1 = new Entry(1);
          palette.set(1, e1);
          assertEquals(BitArrayVersion.V1, palette.getVersion());
          assertEquals(e1, palette.get(1));
  
          var e2 = new Entry(2);
          palette.set(2, e2);
          assertEquals(BitArrayVersion.V2, palette.getVersion());
          assertEquals(e2, palette.get(2));
      }
  
      @Test
      void testOneEntryOnly() {
          var e0 = new Entry(0);
          var e1 = new Entry(1);
          var palette = new Palette<>(e0, BitArrayVersion.V0);
          palette.set(1, e1);
          palette.set(1, e0);
          // Bit array version won't downgrade
          assertEquals(BitArrayVersion.V1, palette.getVersion());
          // But the palette should be one entry only
          assertTrue(palette.oneEntryOnly());
      }
  
      @Test
      void testStorage() {
          var e0 = new Entry(0);
          var e1 = new Entry(1);
          var p0 = new Palette<>(e0, BitArrayVersion.V0);
          p0.set(1, e1);
  
          ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
          p0.writeToStorage(buffer, PDSerializerImpl.INSTANCE);
  
          var p1 = new Palette<>(e0, BitArrayVersion.V0);
          p1.readFromStorage(buffer, PDDeserializerImpl.INSTANCE);
          assertEquals(e0, p1.get(0));
          assertEquals(e1, p1.get(1));
      }
  
      @Test
      void testStorageV2() {
          var e0 = new Entry(0);
          var e1 = new Entry(1);
          var e2 = new Entry(2);
  
          var p0 = new Palette<>(e0, BitArrayVersion.V0);
          p0.set(1, e1);
          p0.set(2, e2);
          ByteBuf b0 = ByteBufAllocator.DEFAULT.buffer();
          p0.writeToStorage(b0, PDSerializerImpl.INSTANCE);
  
          var p1 = new Palette<>(e0, BitArrayVersion.V2);
          p1.set(1, e1);
          p1.set(2, e2);
          ByteBuf b1 = ByteBufAllocator.DEFAULT.buffer();
          p1.writeToStorage(b1, PDSerializerImpl.INSTANCE);
  
          var bytes0 = ByteBufUtil.getBytes(b0);
          var bytes1 = ByteBufUtil.getBytes(b1);
          assertArrayEquals(bytes0, bytes1);
      }
  
      record Entry(int id) {
      }
  
      static class PDSerializerImpl implements NBTSerializer<Entry> {
          static PDSerializerImpl INSTANCE = new PDSerializerImpl();
  
          @Override
          public NbtMap serialize(Entry value) {
              return NbtMap.builder().putInt("id", value.id).build();
          }
      }
  
      static class PDDeserializerImpl implements NBTDeserializer<Entry> {
          static PDDeserializerImpl INSTANCE = new PDDeserializerImpl();
  
          @Override
          public Entry deserialize(ByteBuf buffer) {
              try (var reader = NbtUtils.createReaderLE(new ByteBufInputStream(buffer))) {
                  var nbt = (NbtMap) reader.readTag();
                  return new Entry(nbt.getInt("id"));
              } catch (IOException e) {
                  throw new PaletteException(e);
              }
          }
      }
  }