/*
 * This file is part of GenericsLib for Bukkit, licensed under the MIT License (MIT).
 *
 * Copyright (c) JCThePants (www.jcwhatever.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */


package com.jcwhatever.bukkit.generic;

import com.jcwhatever.bukkit.generic.internal.commands.CommandHandler;
import com.jcwhatever.bukkit.generic.internal.listeners.JCGEventListener;
import com.jcwhatever.bukkit.generic.jail.JailManager;
import com.jcwhatever.bukkit.generic.regions.RegionManager;
import com.jcwhatever.bukkit.generic.utils.PreCon;
import com.sun.istack.internal.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * GenericsLib Bukkit plugin.
 */
public class GenericsLib extends GenericsPlugin {

    private static GenericsLib _instance;
    private static Map<String, GenericsPlugin> _plugins = new HashMap<>(25);

    private JailManager _jailManager;
    private RegionManager _regionManager;

    /**
     * Get the {@code GenericsLib} plugin instance.
     */
    public static GenericsLib getLib() {
        return _instance;
    }

    /**
     * Get a Bukkit plugin that implements {@code GenericsPlugin} by name.
     *
     * @param name  The name of the plugin.
     */
    @Nullable
    public static GenericsPlugin getPlugin(String name) {
        PreCon.notNullOrEmpty(name);

        return _plugins.get(name.toLowerCase());
    }

    /**
     * Get all Bukkit plugins that implement {@code GenericsPlugin}.
     */
    public static List<GenericsPlugin> getPlugins() {
        return new ArrayList<>(_plugins.values());
    }

    /**
     * Get the global {@code RegionManager}.
     */
    public static RegionManager getRegionManager() {
        return _instance._regionManager;
    }

    /**
     * Get the default Jail Manager.
     */
    public static JailManager getJailManager() {
        return _instance._jailManager;
    }

    /**
     * Constructor.
     */
    public GenericsLib() {
        super();

        _instance = this;
    }

    /**
     * Get the chat prefix.
     */
    @Override
    public String getChatPrefix() {
        return "[GenericsLib] ";
    }

    /**
     * Get the console prefix.
     */
    @Override
    public String getConsolePrefix() {
        return getChatPrefix();
    }

    @Override
    protected void onEnablePlugin() {
        _regionManager = new RegionManager();
        _jailManager = new JailManager(this, "default", getDataNode().getNode("jail"));

        registerEventListeners(new JCGEventListener());
        registerCommands(new CommandHandler());
    }

    @Override
    protected void onDisablePlugin() {
        _regionManager = null; // null to prevent exception if re-enabled
    }

    void registerPlugin(GenericsPlugin plugin) {

        _plugins.put(plugin.getName().toLowerCase(), plugin);
    }

    void unregisterPlugin(GenericsPlugin plugin) {

        _plugins.remove(plugin.getName().toLowerCase());
    }
}

@@ -1569,49 +1569,8 @@
 Con;
-%0Aimport com.sun.istack.internal.Nullable;
 %0A%0Aim
@@ -1665,16 +1665,50 @@
 til.Map;
+%0Aimport javax.annotation.Nullable;
 %0A%0A/**%0A *
@@ -1886,17 +1886,132 @@
  _plugin
-s
+NameMap = new HashMap%3C%3E(25);%0A    private static Map%3CClass%3C? extends GenericsPlugin%3E, GenericsPlugin%3E _pluginClassMap
  = new H
@@ -2382,16 +2382,58 @@
 plugin.%0A
+     *%0A     * @return  Null if not found.%0A
      */%0A
@@ -2478,24 +2478,32 @@
 csPlugin get
+Generics
 Plugin(Strin
@@ -2572,17 +2572,23 @@
  _plugin
-s
+NameMap
 .get(nam
@@ -2604,32 +2604,561 @@
 Case());%0A    %7D%0A%0A
+    /**%0A     * Get a Bukkit plugin that implements %7B@code GenericsPlugin%7D.%0A     *%0A     * @param pluginClass  The plugin class.%0A     *%0A     * @param %3CT%3E  The plugin type.%0A     *%0A     * @return  Null if not found.%0A     */%0A    @Nullable%0A    public static %3CT extends GenericsPlugin%3E T getGenericsPlugin(Class%3CT%3E pluginClass) %7B%0A        PreCon.notNull(pluginClass);%0A%0A        GenericsPlugin plugin = _pluginClassMap.get(pluginClass);%0A        if (plugin == null)%0A            return null;%0A%0A        return pluginClass.cast(plugin);%0A    %7D%0A%0A
     /**%0A     * G
@@ -3268,16 +3268,24 @@
 gin%3E get
+Generics
 Plugins(
@@ -3326,17 +3326,23 @@
 (_plugin
-s
+NameMap
 .values(
@@ -4546,17 +4546,23 @@
  _plugin
-s
+NameMap
 .put(plu
@@ -4591,32 +4591,88 @@
 ase(), plugin);%0A
+        _pluginClassMap.put(plugin.getClass(), plugin);%0A
     %7D%0A%0A    void 
@@ -4729,17 +4729,23 @@
  _plugin
-s
+NameMap
 .remove(
@@ -4773,20 +4773,71 @@
 werCase());%0A
+        _pluginClassMap.remove(plugin.getClass());%0A
     %7D%0A%7D%0A

add method to get Generics plugin by class, refactor plugin getters to prevent confusion/conflict with Bukkits plugin getters