package com.airlock.iam.saml2.infrastructure.util;

import com.airlock.iam.core.misc.util.RequestAwareThreadLocal;
import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.saml2.infrastructure.request.Saml2Request;
import com.airlock.iam.saml2.infrastructure.request.Saml2Response;
import com.google.common.base.Preconditions;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Optional;

public final class Saml2RequestThreadContext {
   private static final RequestAwareThreadLocal<Saml2RequestThreadContext> THREAD_LOCAL = new RequestAwareThreadLocal<>();
   private final Saml2Request request;
   private final Saml2Response response;
   private ConfigurationContext context;

   public static void fillWith(HttpServletRequest request, HttpServletResponse response, ConfigurationContext context) {
      Preconditions.checkNotNull(request);
      Preconditions.checkNotNull(response);
      Preconditions.checkNotNull(context);
      THREAD_LOCAL.set(new Saml2RequestThreadContext(new Saml2Request(request), new Saml2Response(response), context));
   }

   public static void fillWith(HttpServletRequest request, HttpServletResponse response) {
      fillWith(request, response, getConfigurationContext());
   }

   public static void setConfigurationContext(ConfigurationContext context) {
      get().orElseThrow().context = context;
   }

   public static ConfigurationContext getConfigurationContext() {
      return get().map(c -> c.context).orElse(ConfigurationContext.defaultContext());
   }

   public static Saml2Request getRequest() {
      return get().orElseThrow().request;
   }

   public static Saml2Response getResponse() {
      return get().orElseThrow().response;
   }

   private static Optional<Saml2RequestThreadContext> get() {
      return Optional.ofNullable(THREAD_LOCAL.get());
   }

   @SuppressFBWarnings(justification = "generated code")
   public Saml2RequestThreadContext(Saml2Request request, Saml2Response response, ConfigurationContext context) {
      this.request = request;
      this.response = response;
      this.context = context;
   }
}
