package de.dhbwstuttgart.server.packet.dataContainers.serialized;

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.HashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;

public class SerialMap extends HashMap<String, ISerialNode> implements ISerialNode {

  public SerialMap() {
    super();
  }

  public SerialMap(Map<String, ISerialNode> data) {
    super(data);
  }

  @JsonIgnore
  public void put(String key, Boolean value) {
    this.put(key, new SerialValue<>(value));
  }

  @JsonIgnore
  public void put(String key, String value) {
    this.put(key, new SerialValue<>(value));
  }

  @JsonIgnore
  public void put(String key, Number value) {
    this.put(key, new SerialValue<>(value));
  }

  @JsonIgnore
  private <T> T get(String key, Class<T> expectedType) {
    if (!this.containsKey(key)) {
      throw new RuntimeException("Missing required value " + key + " in ObjectMap");
    }
    var element = this.get(key);
    if (element != null && element.getClass() != expectedType) {
      throw new RuntimeException(
        "Required value " + key + " to be of type " + expectedType.getName() + " but found " + element.getClass().getName()
      );
    }
    return (T)element;
  }

  @JsonIgnore
  public SerialList<?> getList(String key) {
    return this.get(key, SerialList.class);
  }

  @Nullable
  @JsonIgnore
  public SerialList<?> getListOrNull(String key) {
    return this.containsKey(key) ? this.getList(key) : null;
  }

  @JsonIgnore
  public SerialMap getMap(String key) {
    return this.get(key, SerialMap.class);
  }

  @Nullable
  @JsonIgnore
  public SerialMap getMapOrNull(String key) {
    return this.containsKey(key) ? this.getMap(key) : null;
  }

  @JsonIgnore
  public SerialValue<?> getValue(String key) {
    return this.get(key, SerialValue.class);
  }

  @JsonIgnore
  public SerialUUID getUUID(String key) {
    return this.get(key, SerialUUID.class);
  }

  @Nullable
  @JsonIgnore
  public SerialUUID getUUIDOrNull(String key) {
    return this.containsKey(key) ? this.getUUID(key) : null;
  }
}
