package com.github.yu55.gog;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.LogOutputStream;
import org.apache.commons.exec.PumpStreamHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

@Component
public class GrepService {

    private static final Logger logger = LoggerFactory.getLogger(GrepService.class);

    private static final String COMMAND = "git";

    private static final int SEARCH_LIMIT = 999;

    private Repositories repositories;

    @Autowired
    public GrepService(Repositories repositories) {
        this.repositories = repositories;
    }

    public List<String> grep(GrepRequest wanted) {
        List<String> allFindings = new LinkedList<>();
        List<File> directories = repositories.getDirectories();

        CommandLine commandLine = CommandLine.parse(COMMAND);
        commandLine.addArgument("grep");
        commandLine.addArgument("-n");
        commandLine.addArgument(escapeSearchPhraseArgument(wanted.getWanted()), true);
        DefaultExecutor executor = new DefaultExecutor();
        ExecutorStreamHandler executorStreamHandler = new ExecutorStreamHandler();
        executor.setStreamHandler(new PumpStreamHandler(executorStreamHandler));
        for (File directory : directories) {
            if (wanted.getRepositories().contains(directory.getName())) {
                executor.setWorkingDirectory(directory);
                executorStreamHandler.setRepositoryName(directory.getName());
                try {
                    executor.execute(commandLine);
                    allFindings.addAll(executorStreamHandler.getFindings());
                } catch (IOException e) {
                    logger.warn("Problem while searching '{}' repository: {}", directory.getAbsolutePath(), e.getMessage());
                }
                executorStreamHandler.clearFindings();

                if (allFindings.size() > SEARCH_LIMIT) {
                    allFindings = allFindings.subList(0, SEARCH_LIMIT);
                    allFindings.add(String.format("More results than %d. Aborting...", SEARCH_LIMIT));
                    break;
                }
            }
        }

        if (allFindings.isEmpty()) {
            allFindings.add("No findings in selected repositories.");
        }

        return allFindings;
    }

    private String escapeSearchPhraseArgument(String wanted) {
        if (wanted.startsWith("-") || wanted.startsWith(" ")) {
            return "\\" + wanted;
        } else {
            return wanted;
        }
    }

    private class ExecutorStreamHandler extends LogOutputStream {

        private List<String> findings = new LinkedList<>();
        private String repositoryName = "";

        @Override
        protected void processLine(String line, int logLevel) {
            findings.add(String.format("[%s] %s", repositoryName, line));
        }

        public List<String> getFindings() {
            return findings;
        }

        public void clearFindings() {
            findings.clear();
        }

        public void setRepositoryName(String repositoryName) {
            this.repositoryName = repositoryName;
        }
    }
}

@@ -21,24 +21,131 @@
 u55.gog;%0D%0A%0D%0A
+import java.io.File;%0D%0Aimport java.io.IOException;%0D%0Aimport java.util.LinkedList;%0D%0Aimport java.util.List;%0D%0A%0D%0A
 import org.a
@@ -173,24 +173,24 @@
 mmandLine;%0D%0A
-
 import org.a
@@ -505,115 +505,8 @@
 %0D%0A%0D%0A
-import java.io.File;%0D%0Aimport java.io.IOException;%0D%0Aimport java.util.LinkedList;%0D%0Aimport java.util.List;%0D%0A%0D%0A
 @Com
@@ -731,11 +731,12 @@
 T = 
-999
+1001
 ;%0D%0A%0D
@@ -1175,16 +1175,23 @@
 t(%22grep%22
+, false
 );%0D%0A    
@@ -1222,16 +1222,23 @@
 ent(%22-n%22
+, false
 );%0D%0A    
@@ -1317,11 +1317,12 @@
 )), 
-tru
+fals
 e);%0D

Fix for searching with spaces. Results limit increased to 1001.