package com.airlock.iam.login.rest.application.configuration;

import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.api.exception.PropertyTypeMismatchException;
import com.airlock.iam.plugin.api.valuereader.PluginListPropertyValueReader;
import com.airlock.iam.plugin.api.valuereader.PluginPropertyValueReader;
import com.airlock.iam.plugin.api.valuereader.StringPropertyValueReader;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import lombok.NonNull;

public final class LoginappFlowConfigValidationUtils {
   private LoginappFlowConfigValidationUtils() {
   }

   public static String applicationIdFromApplicationIdConfig(
      PluginConfiguration applicationIdConfig, ConfigurationEnvironment env, ConfigurationContext context
   ) throws PropertyTypeMismatchException {
      return StringPropertyValueReader.effectiveStringConfigValue(applicationIdConfig, "applicationId", env, context);
   }

   public static String applicationIdFromApplicationConfig(PluginConfiguration applicationConfig, ConfigurationEnvironment env, ConfigurationContext context) throws PropertyTypeMismatchException {
      PluginConfiguration applicationIdConfig = applicationIdConfigFromApplicationConfig(applicationConfig, env, context);
      return applicationIdFromApplicationIdConfig(applicationIdConfig, env, context);
   }

   public static PluginConfiguration applicationIdConfigFromApplicationConfig(
      PluginConfiguration applicationConfig, ConfigurationEnvironment env, ConfigurationContext context
   ) throws PropertyTypeMismatchException {
      return PluginPropertyValueReader.effectivePluginPropertyValue(applicationConfig, "applicationId", env, context);
   }

   public static Optional<PluginConfiguration> applicationConfigByApplicationId(
      List<PluginConfiguration> applications, String applicationIdSearched, ConfigurationEnvironment env, ConfigurationContext context
   ) {
      return applications.stream().filter(applicationConfig -> {
         try {
            String applicationId = applicationIdFromApplicationConfig(applicationConfig, env, context);
            return applicationIdSearched.equals(applicationId);
         } catch (PropertyTypeMismatchException e) {
            return false;
         }
      }).findFirst();
   }

   public static class ApplicationConfigs {
      private Optional<PluginConfiguration> defaultApplication;
      @NonNull
      private List<PluginConfiguration> otherApplications;

      public static LoginappFlowConfigValidationUtils.ApplicationConfigs applicationConfigs(
         PluginConfiguration authenticationFlowsConfig, ConfigurationEnvironment env, ConfigurationContext context
      ) throws PropertyTypeMismatchException {
         Optional<PluginConfiguration> defaultApplicationConfig = Optional.ofNullable(
            PluginPropertyValueReader.effectivePluginPropertyValue(authenticationFlowsConfig, "defaultApplication", env, context)
         );
         List<PluginConfiguration> otherApplicationConfigs = PluginListPropertyValueReader.effectivePluginListPropertyValue(
            authenticationFlowsConfig, "applications", env, context
         );
         return new LoginappFlowConfigValidationUtils.ApplicationConfigs(defaultApplicationConfig, otherApplicationConfigs);
      }

      public List<PluginConfiguration> allApplications() {
         List<PluginConfiguration> allApplications = new ArrayList<>();
         this.defaultApplication.ifPresent(allApplications::add);
         allApplications.addAll(this.otherApplications);
         return allApplications;
      }

      @SuppressFBWarnings(justification = "generated code")
      private ApplicationConfigs(Optional<PluginConfiguration> defaultApplication, @NonNull List<PluginConfiguration> otherApplications) {
         if (otherApplications == null) {
            throw new NullPointerException("otherApplications is marked non-null but is null");
         }

         this.defaultApplication = defaultApplication;
         this.otherApplications = otherApplications;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Optional<PluginConfiguration> getDefaultApplication() {
         return this.defaultApplication;
      }

      @NonNull
      @SuppressFBWarnings(justification = "generated code")
      public List<PluginConfiguration> getOtherApplications() {
         return this.otherApplications;
      }
   }
}
