package com.airlock.iam.login.domain.model.attribute;

import com.airlock.iam.base.api.domain.model.mapification.MapifiedValues;
import com.airlock.iam.base.misc.collection.IamMaps;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.flow.shared.api.domain.model.session.UserSessionScopedFlowAttribute;
import com.google.common.base.Strings;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public final class AdditionalPasswordCheckAttributes implements UserSessionScopedFlowAttribute<AdditionalPasswordCheckAttributes> {
   private static final ELogger LOG = ELoggerFactory.getLogger(AdditionalPasswordCheckAttributes.class);
   private final Map<String, String> attributes;

   public static AdditionalPasswordCheckAttributes additionalPasswordCheckAttributes(Map<String, String> rawAttributes) {
      return new AdditionalPasswordCheckAttributes(
         rawAttributes.entrySet().stream().filter(nonEmptyKeyAndValue()).collect(Collectors.toMap(Entry::getKey, Entry::getValue))
      );
   }

   private AdditionalPasswordCheckAttributes(Map<String, String> rawAttributes) {
      this.attributes = Map.copyOf(rawAttributes);
   }

   @Override
   public MapifiedValues mapify() {
      return new MapifiedValues(this.attributes.entrySet().stream().filter(nonEmptyKeyAndValue()).collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
   }

   public AdditionalPasswordCheckAttributes copyAttribute() {
      return new AdditionalPasswordCheckAttributes(this.attributes);
   }

   public AdditionalPasswordCheckAttributes mergeWith(AdditionalPasswordCheckAttributes newAttribute) {
      Map<String, String> result = IamMaps.mergeMaps(this.attributes, newAttribute.getAttributes(), this::logWhenOverriding);
      return additionalPasswordCheckAttributes(result);
   }

   private void logWhenOverriding(String key) {
      LOG.debug("Replacing attribute for key [" + key + "]");
   }

   public static AdditionalPasswordCheckAttributes deserializeSessionAttribute(Map<String, String> rawValues) {
      return additionalPasswordCheckAttributes(rawValues);
   }

   public static AdditionalPasswordCheckAttributes demapify(MapifiedValues values) {
      return additionalPasswordCheckAttributes(values.asStringStringMap());
   }

   private static Predicate<Entry<String, String>> nonEmptyKeyAndValue() {
      return e -> !Strings.isNullOrEmpty(e.getKey()) && !Strings.isNullOrEmpty(e.getValue());
   }

   @SuppressFBWarnings(justification = "generated code")
   public Map<String, String> getAttributes() {
      return this.attributes;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public String toString() {
      return "AdditionalPasswordCheckAttributes(attributes=" + this.getAttributes() + ")";
   }
}
