package com.beolnix.marvin.plugins;

import com.beolnix.marvin.im.api.IMIncomingMessage;
import com.beolnix.marvin.im.api.IMSessionManager;
import com.beolnix.marvin.plugins.api.PluginsManager;
import com.beolnix.marvin.plugins.api.PluginsListener;
import com.beolnix.marvin.plugins.api.PluginsProvider;
import com.beolnix.marvin.plugins.api.IMPlugin;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;

/**
 * Created by beolnix on 31/10/15.
 */
public class PluginsManagerImpl implements PluginsManager, PluginsListener {

    // dependencies
    private final IMSessionManager imSessionManager;
    private final Executor executor;

    // state
    private final Map<String, IMPlugin> pluginsMap = new ConcurrentHashMap<>();
    private List<PluginsProvider> pluginsProvidersList = new ArrayList<>();

    // constants
    private static final Logger logger = Logger.getLogger(PluginsManagerImpl.class);

    public PluginsManagerImpl(IMSessionManager imSessionManager, Executor executor) {
        this.imSessionManager = imSessionManager;
        this.executor = executor;
    }

    public void registerPluginsProvider(PluginsProvider pluginsProvider) {
        pluginsProvider.registerPluginsListener(this);
        pluginsProvidersList.add(pluginsProvider);
        logger.info("New plugins provider registered: " + pluginsProvider.getClass().getName());
    }

    public void process(IMIncomingMessage msg) {
        logger.trace("Processing msg: '" + msg.getRawMessageBody() + "'; from: " + msg.getBotName());
        for (IMPlugin imPlugin : pluginsMap.values()) {
            if (imPlugin.getCommandsList().contains(msg.getCommandName())) {
                executor.execute(() -> imPlugin.process(msg));
            } else if (imPlugin.isProcessAll()) {
                executor.execute(() -> imPlugin.process(msg));
            }
        }
    }

    @Override
    public void deployPlugin(IMPlugin imPlugin) {
        imPlugin.setIMSessionManager(imSessionManager);
        pluginsMap.put(imPlugin.getPluginName(), imPlugin);
        logger.info("New plugin has been deployed: " + imPlugin.getPluginName());
    }

    @Override
    public void undeployPlugin(IMPlugin imPlugin) {
        pluginsMap.remove(imPlugin.getPluginName());
        logger.info("Plugin has been undeployed: " + imPlugin.getPluginName());
    }

}

@@ -175,180 +175,9 @@
 api.
-PluginsManager;%0Aimport com.beolnix.marvin.plugins.api.PluginsListener;%0Aimport com.beolnix.marvin.plugins.api.PluginsProvider;%0Aimport com.beolnix.marvin.plugins.api.IMPlugin
+*
 ;%0Aim
@@ -364,16 +364,52 @@
 xecutor;
+%0Aimport java.util.stream.Collectors;
 %0A%0A/**%0A *
@@ -1532,21 +1532,21 @@
     
-for (
+List%3C
 IMPlugin
  imP
@@ -1545,19 +1545,30 @@
 ugin
+%3E
  i
-m
+nitialized
 Plugin
- :
+s =
  plu
@@ -1583,16 +1583,215 @@
 values()
+.stream()%0A                .filter( plugin -%3E IMPluginState.INITIALIZED == plugin.getPluginState() )%0A                .collect(Collectors.toList());%0A%0A        for (IMPlugin imPlugin : initializedPlugins
 ) %7B%0A    

send messages to process to initialized plugins only