package in.twizmwaz.cardinal.module;

import in.twizmwaz.cardinal.GameHandler;
import in.twizmwaz.cardinal.match.Match;
import in.twizmwaz.cardinal.module.modules.buildHeight.BuildHeightBuilder;
import in.twizmwaz.cardinal.module.modules.cores.CoreObjectiveBuilder;
import in.twizmwaz.cardinal.module.modules.destroyable.DestroyableObjectiveBuilder;
import in.twizmwaz.cardinal.module.modules.difficulty.MapDifficultyBuilder;
import in.twizmwaz.cardinal.module.modules.disableDamage.DisableDamageBuilder;
import in.twizmwaz.cardinal.module.modules.friendlyFire.FriendlyFireBuilder;
import in.twizmwaz.cardinal.module.modules.gamerules.GamerulesBuilder;
import in.twizmwaz.cardinal.module.modules.hunger.HungerBuilder;
import in.twizmwaz.cardinal.module.modules.itemRemove.ItemRemoveBuilder;
import in.twizmwaz.cardinal.module.modules.killStreakCount.KillStreakBuilder;
import in.twizmwaz.cardinal.module.modules.kit.KitBuilder;
import in.twizmwaz.cardinal.module.modules.mapInfo.InfoBuilder;
import in.twizmwaz.cardinal.module.modules.motd.MOTDBuilder;
import in.twizmwaz.cardinal.module.modules.observers.ObserverModuleBuilder;
import in.twizmwaz.cardinal.module.modules.projectiles.ProjectilesBuilder;
import in.twizmwaz.cardinal.module.modules.spawn.SpawnModuleBuilder;
import in.twizmwaz.cardinal.module.modules.team.TeamModuleBuilder;
import in.twizmwaz.cardinal.module.modules.teamPicker.TeamPickerBuilder;
import in.twizmwaz.cardinal.module.modules.timeLock.TimeLockBuilder;
import in.twizmwaz.cardinal.module.modules.tntTracker.TntTrackerBuilder;
import in.twizmwaz.cardinal.module.modules.toolRepair.ToolRepairBuilder;
import in.twizmwaz.cardinal.module.modules.visibility.VisibilityBuilder;
import in.twizmwaz.cardinal.module.modules.wools.WoolObjectiveBuilder;
import in.twizmwaz.cardinal.module.modules.worldFreeze.WorldFreezeBuilder;
import in.twizmwaz.cardinal.teams.PgmTeam;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.jdom2.Document;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;

public class ModuleHandler {

    private final JavaPlugin plugin;
    private final GameHandler gameHandler;

    Set<ModuleBuilder> builders = new HashSet<>();
    private Set<Module> loaded;
    private Set<GameObjective> objectives;

    public ModuleHandler(JavaPlugin plugin, GameHandler gameHandler) {
        this.plugin = plugin;
        this.gameHandler = gameHandler;
        this.loaded = null;
        builders = new HashSet<>();
        builders.add(new BuildHeightBuilder());
        builders.add(new WoolObjectiveBuilder());
        builders.add(new CoreObjectiveBuilder());
        builders.add(new DestroyableObjectiveBuilder());
        builders.add(new ItemRemoveBuilder());
        builders.add(new ToolRepairBuilder());
        builders.add(new DisableDamageBuilder());
        builders.add(new GamerulesBuilder());
        builders.add(new KitBuilder());
        builders.add(new TimeLockBuilder());
        builders.add(new FriendlyFireBuilder());
        builders.add(new HungerBuilder());
        builders.add(new MapDifficultyBuilder());
        builders.add(new HungerBuilder());
        builders.add(new ProjectilesBuilder());
        builders.add(new TntTrackerBuilder());
        builders.add(new VisibilityBuilder());
        builders.add(new MOTDBuilder());
        builders.add(new WorldFreezeBuilder());
        builders.add(new TeamModuleBuilder());
        builders.add(new SpawnModuleBuilder());
        builders.add(new ObserverModuleBuilder());
        builders.add(new KillStreakBuilder());
        builders.add(new TeamPickerBuilder());
        builders.add(new InfoBuilder());
    }

    public Set<Module> invokeModules(Match match) {
        Document document = match.getDocument();
        Set<Module> loaded = new HashSet<Module>();
        for (ModuleBuilder builder : builders) {
            loaded.addAll(builder.load(match));
        }
        this.loaded = loaded;
        Bukkit.getLogger().log(Level.INFO, loaded.size() + " modules loaded.");

        objectives = new HashSet<GameObjective>();
        for (Module loadedModule : loaded) {
            if (loadedModule instanceof GameObjective) {
                objectives.add((GameObjective) loadedModule);
            }
        }
        for (Module module : loaded) {
            plugin.getServer().getPluginManager().registerEvents(module, plugin);
        }
        assignObjectives(match.getTeams());
        return loaded;
    }

    public Set<Module> getModules() {
        return loaded;
    }

    public Set<GameObjective> getConditions() {
        return objectives;
    }

    public void unregisterModules() {
        for (Module module : this.loaded) {
            module.unload();
        }
        this.loaded = null;
        this.objectives = null;
    }

    private void assignObjectives(List<PgmTeam> teams) {
        for (PgmTeam team : teams) {
            Set<GameObjective> objectives = new HashSet<GameObjective>();
            for (GameObjective objective : this.objectives) {
                if (objective.getTeam().equals(team)) {
                    objectives.add(objective);
                }
            }
            team.setObjectives(objectives);
        }
    }


}

@@ -5289,11 +5289,546 @@
 %0A    %7D%0A%0A
+    @SuppressWarnings(%22unchecked%22)%0A    public %3CM extends Module%3E M getModule(Class%3CM%3E clazz) %7B%0A        for (Module module : getModules()) %7B%0A            if (clazz.isInstance(module)) return ((M) module);%0A        %7D%0A        return null;%0A    %7D%0A%0A    @SuppressWarnings(%22unchecked%22)%0A    public %3CM extends Module%3E Set%3CM%3E getModules(Class%3CM%3E clazz) %7B%0A        Set%3CM%3E results = new HashSet%3C%3E();%0A        for (Module module : getModules()) %7B%0A            if (clazz.isInstance(module)) results.add((M) module);%0A        %7D%0A        return results;%0A    %7D
 %0A%7D%0A

Add methods for getting specific modules