package zenith.zov.base.modules;

import com.darkmagician6.eventapi.EventManager;
import com.darkmagician6.eventapi.EventTarget;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.Generated;
import zenith.zov.base.events.impl.input.EventKey;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.impl.combat.AntiBot;
import zenith.zov.client.modules.impl.combat.Aura;
import zenith.zov.client.modules.impl.combat.AutoSwap;
import zenith.zov.client.modules.impl.combat.AutoTotem;
import zenith.zov.client.modules.impl.combat.BackTrack;
import zenith.zov.client.modules.impl.combat.ClickPearl;
import zenith.zov.client.modules.impl.combat.Criticals;
import zenith.zov.client.modules.impl.combat.HitBox;
import zenith.zov.client.modules.impl.combat.MaceAura;
import zenith.zov.client.modules.impl.combat.StunMace;
import zenith.zov.client.modules.impl.combat.TriggerBot;
import zenith.zov.client.modules.impl.crystal.AirAnchor;
import zenith.zov.client.modules.impl.crystal.AnchorMacro;
import zenith.zov.client.modules.impl.crystal.AutoCrystal;
import zenith.zov.client.modules.impl.crystal.AutoHitCrystal;
import zenith.zov.client.modules.impl.crystal.CrystalOptimizer;
import zenith.zov.client.modules.impl.crystal.SafeAnchor;
import zenith.zov.client.modules.impl.misc.AHHelper;
import zenith.zov.client.modules.impl.misc.AutoAccept;
import zenith.zov.client.modules.impl.misc.AutoAuth;
import zenith.zov.client.modules.impl.misc.AutoDuels;
import zenith.zov.client.modules.impl.misc.AutoRespawn;
import zenith.zov.client.modules.impl.misc.AutoSbor;
import zenith.zov.client.modules.impl.misc.BaseFinder;
import zenith.zov.client.modules.impl.misc.ClanUpgrade;
import zenith.zov.client.modules.impl.misc.ClickAction;
import zenith.zov.client.modules.impl.misc.DiscordRPCModule;
import zenith.zov.client.modules.impl.misc.ElytraHelper;
import zenith.zov.client.modules.impl.misc.FastPlace;
import zenith.zov.client.modules.impl.misc.FreeCam;
import zenith.zov.client.modules.impl.misc.ItemScroller;
import zenith.zov.client.modules.impl.misc.NameProtect;
import zenith.zov.client.modules.impl.misc.NoInteract;
import zenith.zov.client.modules.impl.misc.ScoreboardChanger;
import zenith.zov.client.modules.impl.misc.ServerHelper;
import zenith.zov.client.modules.impl.movement.AirStuck;
import zenith.zov.client.modules.impl.movement.AutoPearlCatch;
import zenith.zov.client.modules.impl.movement.AutoSprint;
import zenith.zov.client.modules.impl.movement.ElytraBooster;
import zenith.zov.client.modules.impl.movement.ElytraRecast;
import zenith.zov.client.modules.impl.movement.GuiWalk;
import zenith.zov.client.modules.impl.movement.NoSlow;
import zenith.zov.client.modules.impl.movement.WindHop;
import zenith.zov.client.modules.impl.player.AutoArmor;
import zenith.zov.client.modules.impl.player.AutoTool;
import zenith.zov.client.modules.impl.player.Blink;
import zenith.zov.client.modules.impl.player.FastBreak;
import zenith.zov.client.modules.impl.player.NoDelay;
import zenith.zov.client.modules.impl.render.AntiInvisible;
import zenith.zov.client.modules.impl.render.BlockESP;
import zenith.zov.client.modules.impl.render.CameraTweaks;
import zenith.zov.client.modules.impl.render.ChunkFinder;
import zenith.zov.client.modules.impl.render.Crosshair;
import zenith.zov.client.modules.impl.render.EntityESP;
import zenith.zov.client.modules.impl.render.EntityModifierModule;
import zenith.zov.client.modules.impl.render.HitBubbles;
import zenith.zov.client.modules.impl.render.HitParticles;
import zenith.zov.client.modules.impl.render.Interface;
import zenith.zov.client.modules.impl.render.Menu;
import zenith.zov.client.modules.impl.render.NoRender;
import zenith.zov.client.modules.impl.render.Predictions;
import zenith.zov.client.modules.impl.render.Shaders;
import zenith.zov.client.modules.impl.render.StorageESP;
import zenith.zov.client.modules.impl.render.SwingAnimation;
import zenith.zov.client.modules.impl.render.ViewModel;
import zenith.zov.client.modules.impl.render.WorldTweaks;
import zenith.zov.utility.interfaces.IMinecraft;

public final class ModuleManager implements IMinecraft {
    private final List<Module> modules = new ArrayList<>();

    public ModuleManager() {
        this.init();
        EventManager.register(this);
    }

    private void init() {
        this.registerCrystal();
        this.registerCombat();
        this.registerMovement();
        this.registerRender();
        this.registerPlayer();
        this.registerMisc();
    }

    private void registerCrystal() {
        this.registerModule(AnchorMacro.INSTANCE);
        this.registerModule(AutoCrystal.INSTANCE);
        this.registerModule(AutoHitCrystal.INSTANCE);
        this.registerModule(CrystalOptimizer.INSTANCE);
        this.registerModule(SafeAnchor.INSTANCE);
        this.registerModule(new AirAnchor());
    }

    private void registerCombat() {
        this.registerModule(AntiBot.INSTANCE);
        this.registerModule(Aura.INSTANCE);
        this.registerModule(AutoSwap.INSTANCE);
        this.registerModule(BackTrack.INSTANCE);
        this.registerModule(Criticals.INSTANCE);
        this.registerModule(HitBox.INSTANCE);
        this.registerModule(TriggerBot.INSTANCE);
        this.registerModule(AutoTotem.INSTANCE);
        this.registerModule(ClickPearl.INSTANCE);
        this.registerModule(new MaceAura());
        this.registerModule(new StunMace());
    }

    private void registerMovement() {
        this.registerModule(AutoSprint.INSTANCE);
        this.registerModule(ElytraBooster.INSTANCE);
        this.registerModule(ElytraRecast.INSTANCE);
        this.registerModule(GuiWalk.INSTANCE);
        this.registerModule(NoSlow.INSTANCE);
        this.registerModule(AirStuck.INSTANCE);
        this.registerModule(new WindHop());
        this.registerModule(new AutoPearlCatch());
    }

    private void registerRender() {
        this.registerModule(Interface.INSTANCE);
        this.registerModule(AntiInvisible.INSTANCE);
        this.registerModule(Menu.INSTANCE);
        this.registerModule(NoRender.INSTANCE);
        this.registerModule(Predictions.INSTANCE);
        this.registerModule(BlockESP.INSTANCE);
        this.registerModule(SwingAnimation.INSTANCE);
        this.registerModule(Crosshair.INSTANCE);
        this.registerModule(ViewModel.INSTANCE);
        this.registerModule(WorldTweaks.INSTANCE);
        this.registerModule(EntityESP.INSTANCE);
        this.registerModule(HitBubbles.INSTANCE);
        this.registerModule(HitParticles.INSTANCE);
        this.registerModule(Shaders.INSTANCE);
        this.registerModule(ChunkFinder.INSTANCE);
        this.registerModule(StorageESP.INSTANCE);
        this.registerModule(new EntityModifierModule());
    }

    private void registerPlayer() {
        this.registerModule(AutoTool.INSTANCE);
        this.registerModule(AutoArmor.INSTANCE);
        this.registerModule(Blink.INSTANCE);
        this.registerModule(NoDelay.INSTANCE);
        this.registerModule(FastBreak.INSTANCE);
    }

    private void registerMisc() {
        this.registerModule(ServerHelper.INSTANCE);
        this.registerModule(ElytraHelper.INSTANCE);
        this.registerModule(ItemScroller.INSTANCE);
        this.registerModule(ClickAction.INSTANCE);
        this.registerModule(FreeCam.INSTANCE);
        this.registerModule(CameraTweaks.INSTANCE);
        this.registerModule(AutoAuth.INSTANCE);
        this.registerModule(AutoDuels.INSTANCE);
        this.registerModule(AHHelper.INSTANCE);
        this.registerModule(AutoSbor.INSTANCE);
        this.registerModule(NoInteract.INSTANCE);
        this.registerModule(AutoAccept.INSTANCE);
        this.registerModule(AutoRespawn.INSTANCE);
        this.registerModule(NameProtect.INSTANCE);
        this.registerModule(ClanUpgrade.INSTANCE);
        this.registerModule(DiscordRPCModule.INSTANCE);
        this.registerModule(ScoreboardChanger.INSTANCE);
        this.registerModule(BaseFinder.INSTANCE);
        this.registerModule(FastPlace.INSTANCE);
    }

    private void registerModule(Module module) {
        this.modules.add(module);
    }

    public Module getModule(String name) {
        return this.modules.stream().filter(module -> module.getName().equalsIgnoreCase(name)).findFirst().orElse(null);
    }

    public Set<Module> getActiveModules() {
        Set<Module> active = new HashSet<>();

        for (Module module : this.modules) {
            if (module.isEnabled()) {
                active.add(module);
            }
        }

        return active;
    }

    @EventTarget
    public void onKey(EventKey event) {
        if (mc.currentScreen == null && event.getAction() == 1) {
            for (Module module : this.modules) {
                if (module.getKeyCode() == event.getKeyCode() && module.getKeyCode() != -1) {
                    module.toggle();
                }
            }
        }
    }

    @Generated
    public List<Module> getModules() {
        return this.modules;
    }
}
