package com.airlock.iam.common.infrastructure.factory.uriinfo;

import com.airlock.iam.base.api.infrastructure.uri.ExternalUriInfo;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.UriBuilder;
import jakarta.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.Arrays;
import org.apache.commons.lang3.Strings;
import org.glassfish.jersey.uri.internal.JerseyUriBuilder;

abstract class ExternalUriInfoBase implements ExternalUriInfo {
   private final UriInfo uriInfo;

   protected ExternalUriInfoBase(UriInfo uriInfo) {
      this.uriInfo = uriInfo;
   }

   @Override
   public UriBuilder getBaseUriBuilder() {
      return JerseyUriBuilder.fromUri(this.getBaseUri());
   }

   @Override
   public URI getAbsolutePath() {
      return JerseyUriBuilder.fromUri(this.getRequestUri()).replaceQuery(null).fragment(null).build(new Object[0]);
   }

   @Override
   public String getPath() {
      return this.uriInfo.getPath();
   }

   @Override
   public String getPath(boolean decode) {
      return this.uriInfo.getPath(decode);
   }

   @Override
   public URI getRequestUriUpToContextPath() {
      String path = this.getBaseUri().getPath();
      if (path.isEmpty()) {
         return this.getBaseUri().resolve("/");
      }

      int terminatingSlashIndex = path.indexOf(47, 1);
      return terminatingSlashIndex < 0
         ? this.getBaseUri().resolve(Strings.CS.appendIfMissing(path, "/", new CharSequence[0]))
         : this.getBaseUri().resolve(path.substring(0, terminatingSlashIndex + 1));
   }

   @Override
   public MultivaluedMap<String, String> getQueryParameters() {
      return this.uriInfo.getQueryParameters();
   }

   @Override
   public MultivaluedMap<String, String> getQueryParameters(boolean decode) {
      return this.uriInfo.getQueryParameters(decode);
   }

   protected UriInfo getUriInfo() {
      return this.uriInfo;
   }

   protected URI buildRequestUri(URI requestUri, String... paths) {
      UriBuilder builder = UriBuilder.fromUri(requestUri);
      Arrays.stream(paths).forEach(builder::path);
      return builder.replaceQuery(this.uriInfo.getRequestUri().getRawQuery()).build(new Object[0]);
   }
}
