package wtf.opal.client.feature.module;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import wtf.opal.client.binding.IBindable;
import wtf.opal.client.feature.module.property.IPropertyListProvider;
import wtf.opal.client.feature.module.property.Property;
import wtf.opal.client.feature.module.property.impl.mode.ModeProperty;
import wtf.opal.client.feature.module.property.impl.mode.ModuleMode;
import wtf.opal.event.EventDispatcher;
import wtf.opal.event.impl.client.ModuleToggleEvent;
import wtf.opal.event.subscriber.IEventSubscriber;

@Environment(EnvType.CLIENT)
public class Module implements IBindable, IPropertyListProvider, IEventSubscriber {
   private final String name;
   private final String description;
   @Expose
   @SerializedName("name")
   private final String id;
   private final ModuleCategory category;
   @Expose
   @SerializedName("enabled")
   private boolean enabled;
   @Expose
   @SerializedName("visible")
   private boolean visible = true;
   @Expose
   @SerializedName("properties")
   private final List<Property<?>> propertyList = new ArrayList<>();
   private final List<ModuleMode<?>> moduleModeList = new ArrayList<>();
   private ModeProperty<?> modeProperty;
   private boolean expanded;
   private int propertyIndex;

   protected Module(String name, String description, ModuleCategory category) {
      this.name = name;
      this.id = name.toLowerCase().replace(' ', '_');
      this.description = description;
      this.category = category;
      EventDispatcher.subscribe(this);
   }

   public final void setEnabled(boolean enabled) {
      if (this.enabled != enabled) {
         ModuleToggleEvent var2 = new ModuleToggleEvent(this, enabled);
         EventDispatcher.dispatch(var2);
         if (!var2.isCancelled()) {
            this.enabled = enabled;
            if (enabled) {
               this.onEnable();
            } else {
               this.onDisable();
            }
         }
      }
   }

   public final void toggle() {
      this.setEnabled(!this.isEnabled());
   }

   protected void onEnable() {
      if (this.getActiveMode() != null) {
         this.getActiveMode().onEnable();
      }
   }

   protected void onDisable() {
      if (this.getActiveMode() != null) {
         this.getActiveMode().onDisable();
      }
   }

   public final String getName() {
      return this.name;
   }

   public String getDisplayName() {
      return this.name;
   }

   public final String getId() {
      return this.id;
   }

   public final String getDescription() {
      return this.description;
   }

   public final ModuleCategory getCategory() {
      return this.category;
   }

   public final boolean isEnabled() {
      return this.enabled;
   }

   public final boolean isVisible() {
      return this.visible;
   }

   public final void setVisible(boolean visible) {
      this.visible = visible;
   }

   public final void addProperties(Property<?>... properties) {
      for (Property var5 : properties) {
         if (var5 != null) {
            this.propertyList.add(var5);
         }
      }
   }

   @SafeVarargs
   public final <T extends Module> void addModuleModes(ModeProperty<?> modeProperty, ModuleMode<T>... modes) {
      this.modeProperty = modeProperty;
      Collections.addAll(this.moduleModeList, modes);
   }

   public final List<ModuleMode<?>> getModuleModes() {
      return this.moduleModeList;
   }

   public final ModuleMode<?> getActiveMode() {
      return this.moduleModeList.stream().filter(m -> m.getEnumValue().equals(this.modeProperty.getValue())).findFirst().orElse(null);
   }

   public final ModeProperty<?> getModeProperty() {
      return this.modeProperty;
   }

   public final void setModeProperty(ModeProperty<?> modeProperty) {
      this.modeProperty = modeProperty;
   }

   public String getSuffix() {
      return null;
   }

   public final boolean isExpanded() {
      return this.expanded;
   }

   public final int getPropertyIndex() {
      return this.propertyIndex;
   }

   public final void setPropertyIndex(int propertyIndex) {
      this.propertyIndex = propertyIndex;
   }

   public final void setExpanded(boolean expanded) {
      this.expanded = expanded;
   }

   @Override
   public final List<Property<?>> getPropertyList() {
      return this.propertyList;
   }

   @Override
   public final void onBindingInteraction() {
      this.toggle();
   }

   @Override
   public final boolean isHandlingEvents() {
      return this.enabled;
   }
}
