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

import com.airlock.iam.base.infrastructure.reflection.ClasspathScanner;
import com.airlock.iam.base.infrastructure.scanner.ExcludedPackages;
import com.airlock.iam.elog.api.EDefaultLogType;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.google.common.base.Stopwatch;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public final class PluginDictionaryLoader {
   private static final ELogger LOG = ELoggerFactory.getLogger(PluginDictionaryLoader.class);
   private final PluginDictionary pluginDictionary;

   public PluginDictionaryLoader(PluginDictionaryLoader.Option... options) {
      Stopwatch stopwatch = Stopwatch.createStarted();
      this.pluginDictionary = loadPluginDictionary(Set.of(options).contains(PluginDictionaryLoader.Option.IGNORE_CLASS_LOADING_ERRORS));
      LOG.info(
         EDefaultLogType.GENERIC_LOG_TYPE,
         String.format("Config plugin loading completed (took %s ms) - [plugins: %s]", stopwatch.elapsed(TimeUnit.MILLISECONDS), this.pluginDictionary.count())
      );
   }

   public PluginDictionary getPluginDictionary() {
      return this.pluginDictionary;
   }

   private static PluginDictionary loadPluginDictionary(boolean ignoreClassLoadingErrors) {
      List<Class<?>> pluginClasses = ClasspathScanner.classpathScanner()
         .exclude(ExcludedPackages.EXCLUDED_PACKAGES)
         .getClassesWithAnnotation(Plugin.class, ignoreClassLoadingErrors);
      return new PluginDictionary(pluginClasses);
   }

   public enum Option {
      IGNORE_CLASS_LOADING_ERRORS;
   }
}
