package com.github.jcgay.maven.profiler;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Ordering;
import com.google.common.collect.Table;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.sort;

public class PrintDescriptor {

    @VisibleForTesting int maxKeyLength;
    private Table<MavenProject, MojoExecution, Stopwatch> timers;

    private PrintDescriptor(Table<MavenProject, MojoExecution, Stopwatch> timers) {
        this.timers = timers;
        this.maxKeyLength = findMaxKeyLength(timers.columnKeySet());
    }

    private int findMaxKeyLength(Collection<MojoExecution> mojos) {
        Ordering<MojoExecution> byKeyLength = new Ordering<MojoExecution>() {
            @Override
            public int compare(MojoExecution left, MojoExecution right) {
                return Ints.compare(left.toString().length(), right.toString().length());
            }
        };
        return byKeyLength.max(mojos).toString().length();
    }

    public String getFormattedLine(Map.Entry<MojoExecution, Stopwatch> entry) {
        return String.format(String.format("%-" + maxKeyLength + "s %s", entry.getKey(), entry.getValue()));
    }

    public static PrintDescriptor instance(Table<MavenProject, MojoExecution, Stopwatch> timers) {
        return new PrintDescriptor(timers);
    }

    public List<Map.Entry<MojoExecution, Stopwatch>> getSortedMojosByTime(MavenProject project) {
        List<Map.Entry<MojoExecution, Stopwatch>> result = newArrayList(timers.row(project).entrySet());
        sort(result, new Comparator<Map.Entry<MojoExecution, Stopwatch>>() {
            @Override
            public int compare(Map.Entry<MojoExecution, Stopwatch> o1, Map.Entry<MojoExecution, Stopwatch> o2) {
                return Longs.compare(o2.getValue().elapsedMillis(), o1.getValue().elapsedMillis());
            }
        });
        return result;
    }
}

@@ -87,24 +87,64 @@
 ForTesting;%0A
+import com.google.common.base.Function;%0A
 import com.g
@@ -259,93 +259,8 @@
 le;%0A
-import com.google.common.primitives.Ints;%0Aimport com.google.common.primitives.Longs;%0A
 impo
@@ -381,37 +381,8 @@
 on;%0A
-import java.util.Comparator;%0A
 impo
@@ -427,111 +427,8 @@
 p;%0A%0A
-import static com.google.common.collect.Lists.newArrayList;%0Aimport static java.util.Collections.sort;%0A%0A
 publ
@@ -709,469 +709,47 @@
 h = 
-findMaxKeyLength(timers.columnKeySet());%0A    %7D%0A%0A    private int findMaxKeyLength(Collection%3CMojoExecution%3E mojos) %7B%0A        Ordering%3CMojoExecution%3E byKeyLength = new Ordering%3CMojoExecution%3E() %7B%0A            @Override%0A            public int compare(MojoExecution left, MojoExecution right) %7B%0A                return Ints.compare(left.toString().length(), right.toString().length());%0A            %7D%0A        %7D;%0A        return byKeyLength.max(mojos).toString().length(
+maxToStringLength(timers.columnKeySet()
 );%0A 
@@ -1210,71 +1210,151 @@
     
-List%3CMap.Entry%3CMojoExecution, 
+return Ordering.natural()%0A                .onResultOf(
 Stop
-w
+W
 atch
-%3E%3E result = newArrayList
+Function.toElapsedTime())%0A                .reverse()%0A                .sortedCopy
 (tim
@@ -1391,107 +1391,487 @@
     
+%7D%0A%0A
     
-sort(result, new Comparator%3CMap.Entry%3CMojoExecution, Stopwatch%3E%3E() %7B%0A            @Override
+private int maxToStringLength(Collection%3CMojoExecution%3E mojos) %7B%0A        return MojoFunction.toLength().apply(%0A                Ordering.natural()%0A                        .onResultOf(MojoFunction.toLength())%0A                        .max(mojos)%0A        );%0A    %7D%0A%0A    private static class MojoFunction implements Function%3CMojoExecution, Integer%3E %7B%0A        @Override%0A        public Integer apply(MojoExecution input) %7B%0A            return input.toString().length();
 %0A    
+    %7D%0A%0A
     
@@ -1885,60 +1885,249 @@
 lic 
-int compare(Map.Entry%3CMojoExecution, Stopwatch%3E o1, 
+static MojoFunction toLength() %7B%0A            return new MojoFunction();%0A        %7D%0A    %7D%0A%0A    private static class StopWatchFunction implements Function%3CMap.Entry%3CMojoExecution, Stopwatch%3E, Long%3E %7B%0A        @Override%0A        public Long apply(
 Map.
@@ -2158,18 +2158,21 @@
 pwatch%3E 
-o2
+input
 ) %7B%0A    
@@ -2183,66 +2183,20 @@
     
-   
- 
 return 
-Longs.compare(o2.getValue().elapsedMillis(), o1
+input
 .get
@@ -2218,17 +2218,16 @@
 Millis()
-)
 ;%0A      
@@ -2232,48 +2232,122 @@
     
+%7D%0A%0A
     
-%7D%0A
     
-    %7D);%0A        return result;
+public static StopWatchFunction toElapsedTime() %7B%0A            return new StopWatchFunction();%0A        %7D
 %0A   

Clean Guava Ordering usage.