// @@author A0130195M

package jfdi.logic.commands;

import jfdi.logic.events.SearchDoneEvent;
import jfdi.logic.interfaces.Command;
import jfdi.storage.apis.TaskAttributes;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.stream.Collectors;

/**
 * @author Liu Xinan
 */
public class SearchCommand extends Command {

    private HashSet<String> keywords;

    private SearchCommand(Builder builder) {
        this.keywords = builder.keywords;
    }

    public HashSet<String> getKeywords() {
        return keywords;
    }

    public static class Builder {

        HashSet<String> keywords = new HashSet<>();

        public Builder addKeyword(String keyword) {
            this.keywords.add(keyword);
            return this;
        }

        public Builder addKeywords(Collection<String> keywords) {
            this.keywords.addAll(keywords);
            return this;
        }

        public SearchCommand build() {
            return new SearchCommand(this);
        }

    }

    @Override
    public void execute() {
        Collection<TaskAttributes> allTasks = taskDb.getAll();
        ArrayList<TaskAttributes> results = allTasks.stream().filter(task -> {
            for (String keyword : keywords) {
                if (!task.getDescription().matches(String.format("(?i:.*\\b%s\\b.*)", keyword))) {
                    return false;
                }
            }
            return true;
        }).collect(Collectors.toCollection(ArrayList::new));
        eventBus.post(new SearchDoneEvent(results, keywords));
        System.out.println(results);
    }

    @Override
    public void undo() {
        assert false;
    }

}

@@ -1084,26 +1084,25 @@
         
-Collection
+ArrayList
 %3CTaskAtt
@@ -1114,44 +1114,244 @@
 es%3E 
-allTasks = taskDb.getAll(
+results = new ArrayList%3C%3E();%0A        results.addAll(getFullMatches());%0A        results.addAll(getPartialMatches());%0A%0A        eventBus.post(new SearchDoneEvent(results, keywords));%0A        System.out.println(results
 );%0A    
+%7D%0A%0A
     
+private 
 Arra
@@ -1376,26 +1376,57 @@
 es%3E 
-results = allTasks
+getFullMatches() %7B%0A        return taskDb.getAll()
 .str
@@ -1753,54 +1753,190 @@
     
+%7D%0A%0A
     
-eventBus.post(new SearchDoneEvent(results,
+private ArrayList%3CTaskAttributes%3E getPartialMatches() %7B%0A        return taskDb.getAll().stream().filter(task -%3E %7B%0A            int matches = 0;%0A            for (String keyword :
  key
@@ -1937,35 +1937,39 @@
  : keywords)
-);%0A
+ %7B%0A    
         
 System.out.p
@@ -1960,34 +1960,278 @@
     
-System.out.println(results
+    if (task.getDescription().matches(String.format(%22(?i:.*%5C%5Cb%25s%5C%5Cb.*)%22, keyword))) %7B%0A                    matches++;%0A                %7D%0A            %7D%0A            return matches != 0 && matches != keywords.size();%0A        %7D).collect(Collectors.toCollection(ArrayList::new)
 );%0A 

Improve `SearchCommand` to return partial matches as well