// Path: src/main/java/uk/me/mjt/ch/PartialSolution.java
// public static class DownwardSolution extends PartialSolution {
//     public DownwardSolution(List<DijkstraSolution> ds) {
//         super(ds);
//     }
//     public DownwardSolution(ByteBuffer bb) {
//         super(bb);
//     }
// }
// 
// Path: src/main/java/uk/me/mjt/ch/PartialSolution.java
// public static class UpwardSolution extends PartialSolution {
//     public UpwardSolution(List<DijkstraSolution> ds) {
//         super(ds);
//     }
//     public UpwardSolution(ByteBuffer bb) {
//         super(bb);
//     }
// }


import java.nio.IntBuffer;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;
import uk.me.mjt.ch.PartialSolution.DownwardSolution;
import uk.me.mjt.ch.PartialSolution.UpwardSolution;

package uk.me.mjt.ch;



public class ContractedDijkstra {
    
    public static DijkstraSolution contractedGraphDijkstra(MapData allNodes, Node startNode, Node endNode, ExecutorService es) {
        throw new UnsupportedOperationException("Temporarily broken");
    }
    
    /*public static DijkstraSolution contractedGraphDijkstra(MapData allNodes, Node startNode, Node endNode, ExecutorService es) {
        Preconditions.checkNoneNull(allNodes, startNode, endNode);
        Future<UpwardSolution> fUpwardSolution = futureUpwardSolution(allNodes, startNode, es);
        Future<DownwardSolution> fDownwardSolution = futureDownwardSolution(allNodes, endNode, es);
        
        return mergeUpwardAndDownwardSolutions(allNodes, getFutureQuietly(fUpwardSolution), getFutureQuietly(fDownwardSolution));
    }
    
    private static <E> E getFutureQuietly(Future<E> f) {
        try {
            return f.get();
        } catch (ExecutionException|InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    
    private static Future<UpwardSolution> futureUpwardSolution(final MapData allNodes, final Node startNode, final ExecutorService es) {
        return es.submit(new Callable<UpwardSolution>() {
            @Override
            public UpwardSolution call() throws Exception {
                return calculateUpwardSolution(allNodes, startNode);
            }
        });
    }
    
    private static Future<DownwardSolution> futureDownwardSolution(final MapData allNodes, final Node endNode, final ExecutorService es) {
        return es.submit(new Callable<DownwardSolution>() {
            @Override
            public DownwardSolution call() throws Exception {
                return calculateDownwardSolution(allNodes, endNode);
            }
        });
    }*/
    
    public static DijkstraSolution contractedGraphDijkstra(MapData allNodes, Node startNode, Node endNode) {
        Preconditions.checkNoneNull(allNodes, startNode, endNode);
        return contractedGraphDijkstra(allNodes, ColocatedNodeSet.singleton(startNode), ColocatedNodeSet.singleton(endNode));
    }
    
    public static DijkstraSolution contractedGraphDijkstra(MapData allNodes, ColocatedNodeSet startNode, ColocatedNodeSet endNode) {
        Preconditions.checkNoneNull(allNodes, startNode, endNode);
// Path: src/main/java/uk/me/mjt/ch/PartialSolution.java
// public static class DownwardSolution extends PartialSolution {
//     public DownwardSolution(List<DijkstraSolution> ds) {
//         super(ds);
//     }
//     public DownwardSolution(ByteBuffer bb) {
//         super(bb);
//     }
// }
// 
// Path: src/main/java/uk/me/mjt/ch/PartialSolution.java
// public static class UpwardSolution extends PartialSolution {
//     public UpwardSolution(List<DijkstraSolution> ds) {
//         super(ds);
//     }
//     public UpwardSolution(ByteBuffer bb) {
//         super(bb);
//     }
// }


// Path: src/main/java/uk/me/mjt/ch/ContractedDijkstra.java
import java.nio.IntBuffer;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;
import uk.me.mjt.ch.PartialSolution.DownwardSolution;
import uk.me.mjt.ch.PartialSolution.UpwardSolution;


package uk.me.mjt.ch;



public class ContractedDijkstra {
    
    public static DijkstraSolution contractedGraphDijkstra(MapData allNodes, Node startNode, Node endNode, ExecutorService es) {
        throw new UnsupportedOperationException("Temporarily broken");
    }
    
    /*public static DijkstraSolution contractedGraphDijkstra(MapData allNodes, Node startNode, Node endNode, ExecutorService es) {
        Preconditions.checkNoneNull(allNodes, startNode, endNode);
        Future<UpwardSolution> fUpwardSolution = futureUpwardSolution(allNodes, startNode, es);
        Future<DownwardSolution> fDownwardSolution = futureDownwardSolution(allNodes, endNode, es);
        
        return mergeUpwardAndDownwardSolutions(allNodes, getFutureQuietly(fUpwardSolution), getFutureQuietly(fDownwardSolution));
    }
    
    private static <E> E getFutureQuietly(Future<E> f) {
        try {
            return f.get();
        } catch (ExecutionException|InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    
    private static Future<UpwardSolution> futureUpwardSolution(final MapData allNodes, final Node startNode, final ExecutorService es) {
        return es.submit(new Callable<UpwardSolution>() {
            @Override
            public UpwardSolution call() throws Exception {
                return calculateUpwardSolution(allNodes, startNode);
            }
        });
    }
    
    private static Future<DownwardSolution> futureDownwardSolution(final MapData allNodes, final Node endNode, final ExecutorService es) {
        return es.submit(new Callable<DownwardSolution>() {
            @Override
            public DownwardSolution call() throws Exception {
                return calculateDownwardSolution(allNodes, endNode);
            }
        });
    }*/
    
    public static DijkstraSolution contractedGraphDijkstra(MapData allNodes, Node startNode, Node endNode) {
        Preconditions.checkNoneNull(allNodes, startNode, endNode);
        return contractedGraphDijkstra(allNodes, ColocatedNodeSet.singleton(startNode), ColocatedNodeSet.singleton(endNode));
    }
    
    public static DijkstraSolution contractedGraphDijkstra(MapData allNodes, ColocatedNodeSet startNode, ColocatedNodeSet endNode) {
        Preconditions.checkNoneNull(allNodes, startNode, endNode);
        UpwardSolution upwardSolution = calculateUpwardSolution(startNode);