package pl.mkrystek.mkbot.task;

import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;

import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pl.mkrystek.mkbot.BotProperties;
import pl.mkrystek.mkbot.external.ExternalMessagesService;
import pl.mkrystek.mkbot.window.SkypeWindow;

@Component
public class TaskExecutionEngine {

    private static final Logger LOGGER = LoggerFactory.getLogger(TaskExecutionEngine.class);
    public static final String COMMAND_HELP_BODY = "?";

    @Autowired
    private SkypeWindow skypeWindow;

    @Autowired
    private BotProperties botProperties;

    @Autowired
    private ExternalMessagesService externalMessagesService;

    private final ScheduledExecutorService scheduler;

    private List<ReplyTask> replyTasks;
    private List<ScheduledTask> scheduledTasks;

    public TaskExecutionEngine() {
        this.scheduler = newSingleThreadScheduledExecutor();
    }

    public void init(List<ReplyTask> replyTasks, List<ScheduledTask> scheduledTasks) {
        this.replyTasks = replyTasks;
        this.scheduledTasks = scheduledTasks;
    }

    public void start() {
        scheduler.scheduleAtFixedRate(() -> {
            skypeWindow.getNewMessages().forEach(skypeMessage -> replyTasks.forEach(replyTask -> {
                if (replyTask.checkIfApplies(skypeMessage)) {
                    String reply;
                    if (skypeMessage.getMessageBody().equals(COMMAND_HELP_BODY)) {
                        reply = replyTask.performHelpAction(skypeMessage);
                    } else {
                        reply = replyTask.performAction(skypeMessage);
                    }
                    LOGGER.debug("Writing message on skype: {}", reply);
                    skypeWindow.writeMessage(reply);
                }
            }));
            externalMessagesService.getExternalMessages().forEach(externalMessage -> {
                LOGGER.debug("Writing external message on skype: {}", externalMessage);
                skypeWindow.writeMessage(externalMessage);
            });
        }, 0, botProperties.getPollingFrequency(), TimeUnit.MILLISECONDS);
    }

    public void shutdown() {
        scheduler.shutdownNow();
    }
}

@@ -26,16 +26,73 @@
 .task;%0A%0A
+import static com.google.common.collect.Maps.newHashMap;%0A
 import s
@@ -186,16 +186,38 @@
 l.List;%0A
+import java.util.Map;%0A
 import j
@@ -1065,21 +1065,28 @@
 private 
-List%3C
+Map%3CString, 
 ReplyTas
@@ -1094,24 +1094,39 @@
 %3E replyTasks
+ = newHashMap()
 ;%0A    privat
@@ -1127,21 +1127,28 @@
 private 
-List%3C
+Map%3CString, 
 Schedule
@@ -1168,16 +1168,31 @@
 ledTasks
+ = newHashMap()
 ;%0A%0A    p
@@ -1402,16 +1402,30 @@
 Tasks = 
+createTaskMap(
 replyTas
@@ -1422,24 +1422,25 @@
 p(replyTasks
+)
 ;%0A        th
@@ -1459,30 +1459,301 @@
 Tasks = 
-scheduledTasks
+createTaskMap(scheduledTasks);%0A    %7D%0A%0A    private %3CT extends BotTask%3E Map%3CString, T%3E createTaskMap(List%3CT%3E taskList) %7B%0A        Map%3CString, T%3E map = newHashMap();%0A        taskList.forEach(task -%3E task.getTaskValidNames().forEach(taskName -%3E map.put(taskName, task)));%0A        return map
 ;%0A    %7D%0A
@@ -1894,41 +1894,91 @@
  -%3E 
-replyTasks.forEach(replyTask -%3E %7B
+%7B%0A                ReplyTask replyTask = replyTasks.get(skypeMessage.getTaskName());
 %0A   
@@ -2508,17 +2508,16 @@
       %7D)
-)
 ;%0A      

Refactor task execution routine