package org.dstadler.github;

import com.google.common.base.Preconditions;
import com.google.common.collect.Multimap;
import org.apache.commons.io.IOUtils;
import org.kohsuke.github.GHContent;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import org.kohsuke.github.HttpException;

import java.io.IOException;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Base class for different code-searchers
 */
public abstract class BaseSearch {
    // main definition of which library you are looking for
    protected final static String GROUP_REGEX = "org\\.apache\\.poi";
    protected final static String GROUP = "org.apache.poi";

    protected final static String VERSION = "([-0-9A-Za-z.$_{}()\\[\\]+]+)";

    protected final static String QUOTE = "[\"']?";

    // parse out the name of the repository from the URL returned by the GitHub search
    private final static Pattern REPO_NAME = Pattern.compile("https://github\\.com/([-a-zA-Z0-9_.]+/[-a-zA-Z0-9_.]+)/blob/.*");

    protected void processResults(GitHub github, Multimap<String, String> versions, Iterable<GHContent> list) throws IOException {
        for(GHContent match : list) {
            final String htmlUrl = match.getHtmlUrl();
            String repo = getNonForkRepository(github, htmlUrl);
            if (repo == null) {
                continue;
            }

            String str = readFileContent(match, htmlUrl, repo);
            if (str == null) {
                continue;
            }

            parseVersion(versions, htmlUrl, repo, str);
        }
    }

    protected String readFileContent(GHContent match, String htmlUrl, String repo) throws IOException {
        final InputStream stream;
        try {
            //noinspection resource
            stream = match.read();
        } catch (IOException e) {
            System.out.println("Could not read content of " + htmlUrl + " of repo " + repo + ": " + e);
            return null;
        }

        String str = IOUtils.toString(stream, "UTF-8");

        // filter out some unwanted matches
        str = str.replaceAll(getExcludeRegex(), "");

        // skip this if the group-tag is not found any more now
        if(!str.contains(GROUP)) {
            //System.out.println("Did not find " + GROUP + " in content of repo " + repo + " at " + htmlUrl);
            return null;
        }
        return str;
    }

    abstract void search(GitHub github, Multimap<String, String> versions) throws IOException;

    abstract String getExcludeRegex();

    abstract void parseVersion(Multimap<String, String> versions, String htmlUrl, String repo, String str);

    protected String reducedContent(String str, String htmlUrl) {
        int pos = str.indexOf(GROUP);
        Preconditions.checkState(pos >= 0, "Did not find " + GROUP + " at " + htmlUrl);

        return str.substring(Math.max(0, pos - 100), Math.min(str.length(), pos + 100));
    }

    protected String getNonForkRepository(GitHub github, CharSequence htmlUrl) throws IOException {
        String repo = getRepository(htmlUrl);
        if(repo == null) {
            return null;
        }

        // try up to three times to cater for some connection issues that
        // we see from time to time
        int retries = 3;
        while(true) {
            try {
                final GHRepository repository = github.getRepository(repo);
                if (repository.isFork()) {
                    //System.out.println("Ignoring forked repo " + repo);
                    return null;
                }
                return repo;
            } catch (HttpException e) {
                retries--;

                if(retries <= 0) {
                    throw e;
                }

                // retry once more
                System.out.println("Retry " + retries + " after failing to talk to Github");
                e.printStackTrace(System.out);
            }
        }
    }

    public static String getRepository(CharSequence htmlUrl) {
        Matcher matcher = REPO_NAME.matcher(htmlUrl);
        if(!matcher.matches()) {
            System.out.println("Could not parse repo of " + htmlUrl + " with regex " + REPO_NAME.pattern());
            return null;
        }
        return matcher.group(1);
    }

    protected static GitHub connect() throws IOException {
        return GitHub.connect();
    }
}

@@ -1170,32 +1170,215 @@
 s IOException %7B%0A
+        // try up to three times to cater for some connection issues that%0A        // we see from time to time%0A        int retries = 3;%0A        while(true) %7B%0A            try %7B%0A        
         for(GHCo
@@ -1407,24 +1407,32 @@
             
+        
 final String
@@ -1458,24 +1458,32 @@
 tHtmlUrl();%0A
+        
             
@@ -1539,32 +1539,40 @@
 l);%0A            
+    
+    
 if (repo == null
@@ -1583,32 +1583,40 @@
                 
+        
 continue;%0A      
@@ -1601,32 +1601,40 @@
       continue;%0A
+        
             %7D%0A%0A 
@@ -1636,32 +1636,40 @@
  %7D%0A%0A            
+        
 String str = rea
@@ -1712,24 +1712,32 @@
             
+        
 if (str == n
@@ -1751,32 +1751,40 @@
                 
+    
+    
 continue;%0A      
@@ -1781,35 +1781,51 @@
 ue;%0A            
+      
+  
 %7D%0A%0A
+        
             pars
@@ -1864,16 +1864,398 @@
 , str);%0A
+                %7D%0A%0A                break;%0A            %7D catch (HttpException e) %7B%0A                retries--;%0A%0A                if(retries %3C= 0) %7B%0A                    throw e;%0A                %7D%0A%0A                // retry once more%0A                System.out.println(%22Retry %22 + retries + %22 after failing to talk to Github%22);%0A                e.printStackTrace(System.out);%0A            %7D%0A
         

Add retry on another place where we access GitHub