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

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Function;
import java.util.stream.Stream;

public class SerialList<I extends ISerialNode> extends ArrayList<I> implements ISerialNode {
  public SerialList() {}
  public SerialList(Collection<I> data) {
    this.addAll(data);
  }
  public SerialList(Stream<I> data) {
    this(data.toList());
  }
  public SerialList(I[] data) {
    this(Arrays.stream(data).toList());
  }

  @SafeVarargs
  @JsonIgnore
  public static <A extends ISerialNode> ArrayList<A> from(A ...values) {
    ArrayList<A> list = new SerialList<>();
    Collections.addAll(list, values);
    return list;
  }
  @JsonIgnore
  public static <A,B extends ISerialNode> SerialList<B> fromMapped(Stream<A> data, Function<A,B> mapper) {
    return new SerialList<>(data.map(mapper).toList());
  }
  @JsonIgnore
  public static <A,B extends ISerialNode> SerialList<B> fromMapped(Collection<A> data, Function<A,B> mapper) {
    return SerialList.fromMapped(data.stream(), mapper);
  }
  @JsonIgnore
  public static <A,B extends ISerialNode> SerialList<B> fromMapped(A[] data, Function<A,B> mapper) {
    return SerialList.fromMapped(Arrays.stream(data), mapper);
  }

  @JsonIgnore
  public SerialList<SerialMap> assertListOfMaps() {
    if (this.isEmpty() || this.get(0) instanceof SerialMap) {
      return (SerialList<SerialMap>) this;
    }
    throw new RuntimeException("Required List to contain SerialMap elements but condition failed");
  }

  @JsonIgnore
  public SerialList<SerialList<?>> assertListOfLists() {
    if (this.isEmpty() || this.get(0) instanceof SerialList) {
      return (SerialList<SerialList<?>>) this;
    }
    throw new RuntimeException("Required List to contain SerialList elements but condition failed");
  }

  @JsonIgnore
  public SerialList<SerialValue<?>> assertListOfValues() {
    if (this.isEmpty() || this.get(0) instanceof SerialValue) {
      return (SerialList<SerialValue<?>>) this;
    }
    throw new RuntimeException("Required List to contain SerialValue elements but condition failed");
  }

  @JsonIgnore
  public SerialList<SerialUUID> assertListOfUUIDs() {
    if (this.isEmpty() || this.get(0) instanceof SerialUUID) {
      return (SerialList<SerialUUID>) this;
    }
    throw new RuntimeException("Required List to contain SerialUUID elements but condition failed");
  }
}
