package com.airlock.iam.base.api.domain.model.exception;

import jakarta.annotation.Nullable;
import java.util.Collection;
import java.util.Optional;

public class ViolationException extends RuntimeException {
   public ViolationException(String message) {
      super(message);
   }

   public ViolationException(Throwable cause) {
      super(cause);
   }

   public ViolationException(String message, Throwable cause) {
      super(message, cause);
   }

   public static <T> T checkNotNull(T reference) throws ViolationException {
      return checkNotNull(reference, "A non-null object is required");
   }

   public static <T> T checkPresent(Optional<T> optional, String errorMessage) throws ViolationException {
      return checkNotNull(optional.orElse(null), errorMessage);
   }

   public static void checkNotPresent(Optional<?> optional, String errorMessage) throws ViolationException {
      checkTrue(optional.isEmpty(), errorMessage);
   }

   public static <T> T checkNotNull(@Nullable T reference, String errorMessage) throws ViolationException {
      if (reference == null) {
         throw new ViolationException(errorMessage);
      } else {
         return reference;
      }
   }

   public static void checkTrue(boolean condition, String errorMessage) throws ViolationException {
      if (!condition) {
         throw new ViolationException(errorMessage);
      }
   }

   public static void checkFalse(boolean condition, String errorMessage) throws ViolationException {
      if (condition) {
         throw new ViolationException(errorMessage);
      }
   }

   public static void checkNotEmpty(Collection<?> collection, String errorMessage) throws ViolationException {
      if (collection.isEmpty()) {
         throw new ViolationException(errorMessage);
      }
   }

   public static <T, S extends T> S checkType(T reference, Class<S> type) throws ViolationException {
      if (type.isInstance(reference)) {
         return type.cast(reference);
      } else {
         throw new ViolationException(String.format("Variable of type %s can not be cast to type %s.", reference.getClass(), type));
      }
   }
}
