package io.github.mikesaelim.nomenclature;

import com.google.common.collect.Lists;
import com.google.common.collect.TreeMultimap;
import lombok.Value;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.Tree;
import org.eclipse.egit.github.core.TreeEntry;
import org.eclipse.egit.github.core.service.DataService;

import java.io.IOException;
import java.util.List;
import java.util.Set;

import static java.util.stream.Collectors.toSet;

public class Application {

    public static void main(String[] args) {
        DataService dataService = new DataService();

        Tree tree;
        try {
            tree = dataService.getTree(RepositoryId.create("mikesaelim", "arXivOAIHarvester"), "master", true);
        } catch (IOException e) {
            System.out.println(e.getMessage());
            return;
        }

        TreeMultimap<String, String> javaClassNamesByRoot = extractClassNamesAndCollateByRoot(tree);

        for (String root : javaClassNamesByRoot.keySet()) {
            System.out.println(root + ":");
            for (String className : javaClassNamesByRoot.get(root)) {
                System.out.println("    " + className);
            }
        }
    }

    /**
     * TODO this method's name is intentionally annoying so that I will refactor this into smaller methods later
     * @param tree
     * @return
     */
    private static TreeMultimap<String, String> extractClassNamesAndCollateByRoot(Tree tree) {
        Set<String> classNames = tree.getTree().stream()
                .filter(t -> TreeEntry.TYPE_BLOB.equals(t.getType()))
                .filter(t -> t.getPath().endsWith(".java"))
                .map(t -> t.getPath().substring(t.getPath().lastIndexOf("/") + 1))
                .map(s -> s.substring(0, s.length() - 5))  // TODO use more StringUtils stuff
                .sorted()
                .collect(toSet());

        TreeMultimap<String, String> classNamesByRoot = TreeMultimap.create();

        classNames.stream()
                .filter(StringUtils::isNotBlank)
                .filter(StringUtils::isAlphanumeric)  // TODO other filters?
                .map(Application::tokenize)
                .filter(name -> name.numTokens() >= 2)
                .filter(name -> !name.getRoot().equals("Test"))
                .forEach(name -> classNamesByRoot.put(name.getRoot(), name.getClassName()));

        return classNamesByRoot;
    }

    private static TokenizedClassName tokenize(String className) {
        return new TokenizedClassName(className,
                Lists.newArrayList(StringUtils.splitByCharacterTypeCamelCase(className)));
    }

    @Value
    private static class TokenizedClassName {
        String className;
        List<String> tokens;

        public int numTokens() {
            return tokens.size();
        }

        public String getRoot() {
            return tokens.get(numTokens() - 1);
        }
    }

}

@@ -509,16 +509,149 @@
 s.toSet;
+%0Aimport static org.apache.commons.lang3.StringUtils.removeEnd;%0Aimport static org.apache.commons.lang3.StringUtils.substringAfterLast;
 %0A%0Apublic
@@ -1187,24 +1187,93 @@
 keySet()) %7B%0A
+            Set%3CString%3E classNames = javaClassNamesByRoot.get(root);%0A
             
@@ -1299,16 +1299,44 @@
 root + %22
+ (%22 + classNames.size() + %22)
 :%22);%0A   
@@ -1368,21 +1368,17 @@
 sName : 
-javaC
+c
 lassName
@@ -1378,32 +1378,16 @@
 assNames
-ByRoot.get(root)
 ) %7B%0A    
@@ -1944,158 +1944,94 @@
  -%3E 
-t.getPath().substring(t.getPath().lastIndexOf(%22/%22) + 1))%0A                .map(s -%3E s.substring(0, s.length() - 5))  // TODO use more StringUtils stuff
+substringAfterLast(t.getPath(), %22/%22))%0A                .map(s -%3E removeEnd(s, %22.java%22))
 %0A   
@@ -2246,16 +2246,16 @@
 tBlank)%0A
+
         
@@ -2302,32 +2302,8 @@
 ric)
-  // TODO other filters?
 %0A   

use StringUtils better