package com.airlock.iam.plugin.framework.misc.dictionary;

import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.api.property.PropertyConfiguration;
import com.airlock.iam.plugin.framework.application.configuration.MutablePluginConfiguration;
import com.google.common.collect.Sets;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Set;
import lombok.NonNull;

public final class CompositionalParents {
   @NonNull
   private final Set<MutablePluginConfiguration> pool;
   @NonNull
   private final PluginConfiguration pluginConfiguration;

   public boolean hasCompositionalParents() {
      for (PluginConfiguration parentCandidate : this.pool) {
         if (parentCandidate != this.pluginConfiguration) {
            for (ConfigurationEnvironment env : parentCandidate.getLocallyUsedConfigurationEnvironments()) {
               for (PropertyConfiguration propertyConfiguration : parentCandidate.getEnvironmentSpecificProperties(env).getAllProperties()) {
                  for (PluginConfiguration configuration : propertyConfiguration.getDirectlyReferenced()) {
                     if (this.pluginConfiguration == configuration) {
                        return true;
                     }
                  }
               }
            }
         }
      }

      return false;
   }

   public Set<PluginConfiguration> getAllCompositionalParents() {
      Set<PluginConfiguration> compositionalParents = Sets.newHashSet();

      for (PluginConfiguration parentCandidate : this.pool) {
         if (parentCandidate != this.pluginConfiguration) {
            for (ConfigurationEnvironment env : parentCandidate.getLocallyUsedConfigurationEnvironments()) {
               for (PropertyConfiguration propertyConfiguration : parentCandidate.getEnvironmentSpecificProperties(env).getAllProperties()) {
                  for (PluginConfiguration configuration : propertyConfiguration.getDirectlyReferenced()) {
                     if (this.pluginConfiguration == configuration) {
                        compositionalParents.add(parentCandidate);
                     }
                  }
               }
            }
         }
      }

      return compositionalParents;
   }

   @SuppressFBWarnings(justification = "generated code")
   CompositionalParents(@NonNull Set<MutablePluginConfiguration> pool, @NonNull PluginConfiguration pluginConfiguration) {
      if (pool == null) {
         throw new NullPointerException("pool is marked non-null but is null");
      }

      if (pluginConfiguration == null) {
         throw new NullPointerException("pluginConfiguration is marked non-null but is null");
      }

      this.pool = pool;
      this.pluginConfiguration = pluginConfiguration;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class CompositionalParentsBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Set<MutablePluginConfiguration> pool;
      @SuppressFBWarnings(justification = "generated code")
      private PluginConfiguration pluginConfiguration;

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

      @SuppressFBWarnings(justification = "generated code")
      public CompositionalParents.CompositionalParentsBuilder pool(@NonNull Set<MutablePluginConfiguration> pool) {
         if (pool == null) {
            throw new NullPointerException("pool is marked non-null but is null");
         }

         this.pool = pool;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public CompositionalParents.CompositionalParentsBuilder pluginConfiguration(@NonNull PluginConfiguration pluginConfiguration) {
         if (pluginConfiguration == null) {
            throw new NullPointerException("pluginConfiguration is marked non-null but is null");
         }

         this.pluginConfiguration = pluginConfiguration;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public CompositionalParents build() {
         return new CompositionalParents(this.pool, this.pluginConfiguration);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "CompositionalParents.CompositionalParentsBuilder(pool=" + this.pool + ", pluginConfiguration=" + this.pluginConfiguration + ")";
      }
   }
}
