package wtf.opal.client.feature.module.repository;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.UnmodifiableIterator;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import wtf.opal.client.feature.module.Module;
import wtf.opal.client.feature.module.ModuleCategory;
import wtf.opal.client.feature.module.UnknownModuleException;
import wtf.opal.client.feature.module.impl.crucifix.CrucifixModuleAdapter;

@Environment(EnvType.CLIENT)
public final class ModuleRepository {
   private final ImmutableMap<Class<? extends Module>, Module> classToInstanceMap;
   private final ImmutableMap<String, Module> idToInstanceMap;

   private ModuleRepository(ImmutableMap<Class<? extends Module>, Module> classToInstanceMap, ImmutableMap<String, Module> idToInstanceMap) {
      this.classToInstanceMap = classToInstanceMap;
      this.idToInstanceMap = idToInstanceMap;
   }

   public void findModule(String id, Consumer<Module> moduleConsumer, Consumer<UnknownModuleException> exceptionHandler) {
      try {
         moduleConsumer.accept(this.getModule(id));
      } catch (UnknownModuleException var5) {
         exceptionHandler.accept(var5);
      }
   }

   public <T extends Module> T getModule(Class<T> moduleClass) {
      this.syncExternalModuleStates();
      return (T)this.classToInstanceMap.get(moduleClass);
   }

   public Module getModule(String id) throws UnknownModuleException {
      this.syncExternalModuleStates();
      Module var2 = (Module)this.idToInstanceMap.get(id);
      if (var2 == null) {
         throw new UnknownModuleException(id);
      } else {
         return var2;
      }
   }

   public Collection<Module> getModules() {
      this.syncExternalModuleStates();
      return this.idToInstanceMap.values();
   }

   public Collection<Module> getModulesInCategory(ModuleCategory category) {
      this.syncExternalModuleStates();
      return this.idToInstanceMap.values().stream().filter(module -> category.equals(module.getCategory())).collect(Collectors.toList());
   }

   private void syncExternalModuleStates() {
      UnmodifiableIterator var1 = this.idToInstanceMap.values().iterator();

      while (var1.hasNext()) {
         Module var2 = (Module)var1.next();
         if (var2 instanceof CrucifixModuleAdapter var3) {
            var3.syncEnabledFromDelegate();
         }
      }
   }

   public static ModuleRepository fromModules(Module... modules) {
      ModuleRepository.Builder var1 = builder();

      for (Module var5 : modules) {
         var1.register(var5);
      }

      return var1.build();
   }

   public static ModuleRepository.Builder builder() {
      return new ModuleRepository.Builder();
   }

   @Environment(EnvType.CLIENT)
   public static class Builder {
      private final Map<Class<? extends Module>, Module> classToInstanceMap = new LinkedHashMap<>();
      private final Map<String, Module> idToInstanceMap = new LinkedHashMap<>();

      private Builder() {
      }

      public ModuleRepository.Builder register(Module module) {
         this.classToInstanceMap.putIfAbsent((Class<? extends Module>)module.getClass(), module);
         this.idToInstanceMap.put(module.getId(), module);
         return this;
      }

      public ModuleRepository build() {
         return new ModuleRepository(ImmutableMap.copyOf(this.classToInstanceMap), ImmutableMap.copyOf(this.idToInstanceMap));
      }
   }
}
