content: package org.allaymc.api.block.property.type;
  
  import lombok.Getter;
  import org.allaymc.api.utils.Utils;
  
  import java.util.Arrays;
  import java.util.EnumMap;
  import java.util.HashMap;
  import java.util.Locale;
  
  /**
   * @author daoge_cmd
   */
  public final class EnumPropertyType<T extends Enum<T>> extends BaseBlockPropertyType<T> {
  
      private final EnumMap<T, EnumPropertyValue> cachedValues;
      private final Class<T> enumClass;
  
      private EnumPropertyType(String name, Class<T> enumClass, T defaultData) {
          super(name, Arrays.asList(enumClass.getEnumConstants()), defaultData, Utils.computeRequiredBits(enumClass.getEnumConstants().length));
          this.enumClass = enumClass;
          var map = new HashMap<T, EnumPropertyValue>();
          for (var value : validValues) {
              map.put(value, new EnumPropertyValue(value));
          }
          cachedValues = new EnumMap<>(map);
      }
  
      public static <T extends Enum<T>> EnumPropertyType<T> of(String name, Class<T> enumClass, T defaultData) {
          return new EnumPropertyType<>(name, enumClass, defaultData);
      }
  
      @Override
      public Type getType() {
          return Type.ENUM;
      }
  
      @Override
      public EnumPropertyValue createValue(T value) {
          return cachedValues.get(value);
      }
  
      @Override
      public EnumPropertyValue tryCreateValue(Object value) {
          if (enumClass.isInstance(value)) {
              return cachedValues.get(enumClass.cast(value));
          } else if (value instanceof String str) {
              return cachedValues.get(Enum.valueOf(enumClass, str.toUpperCase(Locale.ROOT)));
          }
          throw new IllegalArgumentException("Invalid value for enum property type: " + value);
      }
  
      public final class EnumPropertyValue extends BlockPropertyValue<T, EnumPropertyType<T>, String> {
          @Getter
          private final String serializedValue;
  
          EnumPropertyValue(T value) {
              super(EnumPropertyType.this, value);
              this.serializedValue = value.name().toLowerCase(Locale.ROOT);
          }
  
          @Override
          public int getIndex() {
              return value.ordinal();
          }
  
          @Override
          public String toString() {
              return "EnumPropertyValue(name=" + name + ", value=" + value + ")";
          }
      }
  }
  