content: package org.allaymc.api.block.type;
  
  import lombok.experimental.UtilityClass;
  import lombok.extern.slf4j.Slf4j;
  import org.allaymc.api.utils.NBTIO;
  import org.cloudburstmc.nbt.NbtMap;
  import org.cloudburstmc.nbt.NbtMapBuilder;
  
  /**
   * BlockStateGetter is used to get a block state safely using {@link NBTIO}, which means
   * that the plugin developers can get an item type without worrying about being broken
   * in the next minecraft version compared to using {@link BlockTypes} directly.
   *
   * @author daoge_cmd | harry-xi
   */
  @Slf4j
  @UtilityClass
  public final class BlockStateGetter {
      /**
       * Get a block type by its name.
       *
       * @param name The name of the block type
       * @return The {@link BlockStateGetter.Getter} object
       */
      public static Getter name(String name) {
          return new Getter(name);
      }
  
      public static final class Getter {
          private final NbtMapBuilder nbtBuilder = NbtMap.builder();
          private NbtMapBuilder stateBuilder;
  
          private Getter(String name) {
              if (name.isBlank()) {
                  throw new IllegalArgumentException("Name cannot be blank");
              }
              nbtBuilder.putString("name", name);
          }
  
          /**
           * Set the property of the block.
           *
           * @param name  The name of the property
           * @param value The value of the property
           * @return The {@link Getter} object
           */
          public Getter property(String name, Object value) {
              if (nbtBuilder.containsKey("val")) {
                  throw new IllegalStateException("Cannot set properties when val is set");
              }
              if (stateBuilder == null) {
                  stateBuilder = NbtMap.builder();
              }
              stateBuilder.put(name, value);
              return this;
          }
  
          /**
           * Set the val of the block.
           *
           * @param val The val of the block
           * @return The {@link Getter} object
           */
          public Getter val(int val) {
              if (stateBuilder != null) {
                  throw new IllegalStateException("Cannot set val when properties are set");
              }
              nbtBuilder.putInt("val", val);
              return this;
          }
  
          /**
           * Try to get the block state.
           *
           * @return the block state, or the default state of {@link BlockTypes#UNKNOWN} if failed to get the block state
           */
          public BlockState blockState() {
              if (stateBuilder != null) {
                  nbtBuilder.putCompound("states", stateBuilder.build());
              }
  
              return NBTIO.getAPI().fromBlockStateNBT(nbtBuilder.build());
          }
      }
  }