package com.airlock.iam.common.domain.model.request;

import com.airlock.iam.common.api.domain.model.geolocation.Geolocation;
import com.airlock.iam.common.api.domain.model.request.IpAddress;
import com.airlock.iam.common.api.domain.model.request.RequestAttributes;
import com.airlock.iam.core.domain.model.header.HttpHeader;
import com.google.common.collect.ImmutableList;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Optional;

public class RequestAttributesImpl implements RequestAttributes {
   private final IpAddress clientIp;
   private final List<HttpHeader> httpHeaders;
   private final Optional<Geolocation> geolocation;

   @Override
   public IpAddress getClientIp() {
      return this.clientIp;
   }

   @Override
   public Optional<String> getHeader(String name) {
      for (HttpHeader header : this.httpHeaders) {
         if (header.getName().equalsIgnoreCase(name)) {
            return Optional.of(header.getValue());
         }
      }

      return Optional.empty();
   }

   @Override
   public List<String> getHeaderNames() {
      List<String> headers = new ArrayList<>(this.httpHeaders.size());

      for (HttpHeader header : this.httpHeaders) {
         headers.add(header.getName().toLowerCase(Locale.ENGLISH));
      }

      return ImmutableList.copyOf(headers);
   }

   @Override
   public Optional<Geolocation> getGeolocation() {
      return this.geolocation;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static RequestAttributesImpl.RequestAttributesImplBuilder builder() {
      return new RequestAttributesImpl.RequestAttributesImplBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public RequestAttributesImpl(IpAddress clientIp, List<HttpHeader> httpHeaders, Optional<Geolocation> geolocation) {
      this.clientIp = clientIp;
      this.httpHeaders = httpHeaders;
      this.geolocation = geolocation;
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public String toString() {
      return "RequestAttributesImpl(clientIp=" + this.getClientIp() + ", httpHeaders=" + this.httpHeaders + ", geolocation=" + this.getGeolocation() + ")";
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public boolean equals(Object o) {
      if (o == this) {
         return true;
      } else if (!(o instanceof RequestAttributesImpl other)) {
         return false;
      } else {
         if (!other.canEqual(this)) {
            return false;
         }

         Object this$clientIp = this.clientIp;
         Object other$clientIp = other.clientIp;
         if (this$clientIp == null ? other$clientIp == null : this$clientIp.equals(other$clientIp)) {
            Object this$httpHeaders = this.httpHeaders;
            Object other$httpHeaders = other.httpHeaders;
            if (this$httpHeaders == null ? other$httpHeaders == null : this$httpHeaders.equals(other$httpHeaders)) {
               Object this$geolocation = this.geolocation;
               Object other$geolocation = other.geolocation;
               return this$geolocation == null ? other$geolocation == null : this$geolocation.equals(other$geolocation);
            } else {
               return false;
            }
         } else {
            return false;
         }
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   protected boolean canEqual(Object other) {
      return other instanceof RequestAttributesImpl;
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public int hashCode() {
      int PRIME = 59;
      int result = 1;
      Object $clientIp = this.clientIp;
      result = result * 59 + ($clientIp == null ? 43 : $clientIp.hashCode());
      Object $httpHeaders = this.httpHeaders;
      result = result * 59 + ($httpHeaders == null ? 43 : $httpHeaders.hashCode());
      Object $geolocation = this.geolocation;
      return result * 59 + ($geolocation == null ? 43 : $geolocation.hashCode());
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class RequestAttributesImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private IpAddress clientIp;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<HttpHeader> httpHeaders;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<Geolocation> geolocation;

      @SuppressFBWarnings(justification = "generated code")
      RequestAttributesImplBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public RequestAttributesImpl.RequestAttributesImplBuilder clientIp(IpAddress clientIp) {
         this.clientIp = clientIp;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RequestAttributesImpl.RequestAttributesImplBuilder httpHeader(HttpHeader httpHeader) {
         if (this.httpHeaders == null) {
            this.httpHeaders = new ArrayList<>();
         }

         this.httpHeaders.add(httpHeader);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RequestAttributesImpl.RequestAttributesImplBuilder httpHeaders(Collection<? extends HttpHeader> httpHeaders) {
         if (httpHeaders == null) {
            throw new NullPointerException("httpHeaders cannot be null");
         }

         if (this.httpHeaders == null) {
            this.httpHeaders = new ArrayList<>();
         }

         this.httpHeaders.addAll(httpHeaders);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RequestAttributesImpl.RequestAttributesImplBuilder clearHttpHeaders() {
         if (this.httpHeaders != null) {
            this.httpHeaders.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RequestAttributesImpl.RequestAttributesImplBuilder geolocation(Optional<Geolocation> geolocation) {
         this.geolocation = geolocation;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RequestAttributesImpl build() {
         return new RequestAttributesImpl(this.clientIp, switch (this.httpHeaders == null ? 0 : this.httpHeaders.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.httpHeaders.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.httpHeaders));
         }, this.geolocation);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "RequestAttributesImpl.RequestAttributesImplBuilder(clientIp="
            + this.clientIp
            + ", httpHeaders="
            + this.httpHeaders
            + ", geolocation="
            + this.geolocation
            + ")";
      }
   }
}
