package com.airlock.iam.oauth2.domain.model.client.communication;

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.base.api.domain.model.mapification.MapifiedValues;
import com.airlock.iam.base.domain.model.mapification.MapifiedValuesBuilder;
import com.airlock.iam.flow.shared.api.domain.model.session.UserSessionScopedFlowAttribute;
import com.airlock.iam.flow.shared.domain.model.idpropagation.SingleLogoutRedirectUrisAttribute;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;

public final class LogoutPropagationAttribute implements UserSessionScopedFlowAttribute<LogoutPropagationAttribute>, SingleLogoutRedirectUrisAttribute {
   private static final String URLS_KEY = "logoutPropagationUris";
   private static final String URI_DELIMITER = " ";
   private final List<URI> sloRedirectUris;

   public LogoutPropagationAttribute(List<URI> sloRedirectUris) {
      this.sloRedirectUris = sloRedirectUris;
   }

   public LogoutPropagationAttribute mergeWith(LogoutPropagationAttribute newAttribute) {
      throw new FailureException("Cannot replace logout propagation URI");
   }

   public LogoutPropagationAttribute copyAttribute() {
      return new LogoutPropagationAttribute(this.sloRedirectUris);
   }

   @Override
   public List<URI> getSloRedirectUris() {
      return Collections.unmodifiableList(this.sloRedirectUris);
   }

   @Override
   public MapifiedValues mapify() {
      return MapifiedValuesBuilder.mapifiedValues().putIfNotEmpty("logoutPropagationUris", this.sloRedirectUris.stream().map(URI::toString).toList()).build();
   }

   public static LogoutPropagationAttribute demapify(MapifiedValues values) {
      return new LogoutPropagationAttribute(values.<String>getList("logoutPropagationUris").stream().map(URI::create).toList());
   }

   public static LogoutPropagationAttribute deserializeSessionAttribute(Map<String, String> rawValues) {
      List<URI> logoutPropagationUri = Optional.ofNullable(rawValues.get("logoutPropagationUris"))
         .filter(StringUtils::isNotBlank)
         .map(uris -> Stream.of(uris.split(" ")).map(URI::create).collect(Collectors.toList()))
         .orElseThrow(() -> new FailureException("Failed to deserialize logoutPropagationUri"));
      return new LogoutPropagationAttribute(logoutPropagationUri);
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public boolean equals(Object o) {
      if (o == this) {
         return true;
      } else if (!(o instanceof LogoutPropagationAttribute other)) {
         return false;
      } else {
         Object this$sloRedirectUris = this.sloRedirectUris;
         Object other$sloRedirectUris = other.sloRedirectUris;
         return this$sloRedirectUris == null ? other$sloRedirectUris == null : this$sloRedirectUris.equals(other$sloRedirectUris);
      }
   }

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

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public String toString() {
      return "LogoutPropagationAttribute(sloRedirectUris=" + this.getSloRedirectUris() + ")";
   }
}
