// Path: backport/src/java/util/stream/Collectors.java
// public class Collectors {
//   public static <T, K, V> Collector<T, ?, Map<K,V>> toMap(Function<? super T, ? extends K> keyMapper,
//                                                           Function<? super T, ? extends V> valueMapper) {
//     return stream -> {
//       HashMap<K, V> map = new HashMap<>();
//       stream.forEach(element -> {
//         map.put(keyMapper.apply(element), valueMapper.apply(element));
//       });
//       return map;
//     };
//   }
// 
//   public static <T> Collector<T, ?, Set<T>> toSet() {
//     return toCollection(HashSet::new);
//   }
//   
//   public static <T> Collector<T, ?, List<T>> toList() {
//     return toCollection(ArrayList::new);
//   }
//   
//   private static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
//     return stream -> {
//       C collection = collectionFactory.get();
//       stream.forEach(collection::add);
//       return collection;
//     };
//   }
// }


import static org.objectweb.asm.Opcodes.ASM5;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import java.io.IOException;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.stream.Collectors;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.RemappingClassAdapter;
  }
  
  static Handle RETRO_BSM = new Handle(Opcodes.H_INVOKESTATIC,
      "com/github/forax/jrtfs/backport/rt/Enhancements",
      "metafactory",
      MethodType.methodType(CallSite.class, Lookup.class, String.class, MethodType.class,
                                            MethodType.class, MethodHandle.class, MethodType.class
                           ).toMethodDescriptorString());
  
  public static void main(String[] args) throws IOException {
    Path backportClasses = Paths.get("output/backport/classes");
    Path retroClasses = Paths.get("output/retro/classes");
    Path outputClasses = Paths.get("output/classes");
    
    RetroWeaver retroWeaver = new RetroWeaver();
    
    // add classes
    Files.walk(backportClasses)
         .forEach(path -> {
           Path localPath = backportClasses.relativize(path);
           String filename = localPath.toString();
           
           if (filename.endsWith(".class")) {
             String internalName = filename.substring(0, filename.length() - 6);
             System.out.println("need to repackage " + internalName);
             retroWeaver.addNewClass(internalName);
           }
         });
    
    // retro weave
// Path: backport/src/java/util/stream/Collectors.java
// public class Collectors {
//   public static <T, K, V> Collector<T, ?, Map<K,V>> toMap(Function<? super T, ? extends K> keyMapper,
//                                                           Function<? super T, ? extends V> valueMapper) {
//     return stream -> {
//       HashMap<K, V> map = new HashMap<>();
//       stream.forEach(element -> {
//         map.put(keyMapper.apply(element), valueMapper.apply(element));
//       });
//       return map;
//     };
//   }
// 
//   public static <T> Collector<T, ?, Set<T>> toSet() {
//     return toCollection(HashSet::new);
//   }
//   
//   public static <T> Collector<T, ?, List<T>> toList() {
//     return toCollection(ArrayList::new);
//   }
//   
//   private static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
//     return stream -> {
//       C collection = collectionFactory.get();
//       stream.forEach(collection::add);
//       return collection;
//     };
//   }
// }


// Path: backport-build/src/com/github/forax/jrtfs/backport/RetroWeaver.java
import static org.objectweb.asm.Opcodes.ASM5;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import java.io.IOException;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.stream.Collectors;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.RemappingClassAdapter;

  }
  
  static Handle RETRO_BSM = new Handle(Opcodes.H_INVOKESTATIC,
      "com/github/forax/jrtfs/backport/rt/Enhancements",
      "metafactory",
      MethodType.methodType(CallSite.class, Lookup.class, String.class, MethodType.class,
                                            MethodType.class, MethodHandle.class, MethodType.class
                           ).toMethodDescriptorString());
  
  public static void main(String[] args) throws IOException {
    Path backportClasses = Paths.get("output/backport/classes");
    Path retroClasses = Paths.get("output/retro/classes");
    Path outputClasses = Paths.get("output/classes");
    
    RetroWeaver retroWeaver = new RetroWeaver();
    
    // add classes
    Files.walk(backportClasses)
         .forEach(path -> {
           Path localPath = backportClasses.relativize(path);
           String filename = localPath.toString();
           
           if (filename.endsWith(".class")) {
             String internalName = filename.substring(0, filename.length() - 6);
             System.out.println("need to repackage " + internalName);
             retroWeaver.addNewClass(internalName);
           }
         });
    
    // retro weave
    for(Path path: Files.walk(retroClasses).filter(path -> !Files.isDirectory(path)).collect(Collectors.toList())) {