class RoundTripRoutingTemplate extends AbstractRoutingTemplate implements RoutingTemplate {

    @Override
    public List<QueryResult> lookup(List<GHPoint> points) {
        if (points.size() != 1 || ghRequest.getPoints().size() != 1)
            throw new IllegalArgumentException("For round trip calculation exactly one point is required");
        final double distanceInMeter = ghRequest.getHints().getDouble(RoundTrip.DISTANCE, 10000);
        final long seed = ghRequest.getHints().getLong(RoundTrip.SEED, 0L);
        double initialHeading = ghRequest.getFavoredHeading(0);
        final int roundTripPointCount = Math.min(20, ghRequest.getHints().getInt(RoundTrip.POINTS, 2 + (int) (distanceInMeter / 50000)));
        final GHPoint start = points.get(0);

        TourStrategy strategy = new MultiPointTour(new Random(seed), distanceInMeter, roundTripPointCount, initialHeading);
        queryResults = new ArrayList<>(2 + strategy.getNumberOfGeneratedPoints());
        QueryResult startQR = locationIndex.findClosest(start.lat, start.lon, edgeFilter);
        if (!startQR.isValid())
            throw new PointNotFoundException("Cannot find point 0: " + start, 0);

        queryResults.add(startQR);

        GHPoint last = start;
        for (int i = 0; i < strategy.getNumberOfGeneratedPoints(); i++) {
            double heading = strategy.getHeadingForIteration(i);
            QueryResult result = generateValidPoint(last, strategy.getDistanceForIteration(i), heading, edgeFilter);
            if (result == null) {
                ghResponse.addError(new IllegalStateException("Could not find a valid point after " + maxRetries + " tries, for the point:" + last));
                return Collections.emptyList();
            }
            last = result.getSnappedPoint();
            queryResults.add(result);
        }

        queryResults.add(startQR);
        return queryResults;
    }

    public  RoundTripRoutingTemplate(GHRequest request, GHResponse ghRsp, LocationIndex locationIndex,
                                    EncodedValueLookup lookup, Weighting weighting, int maxRetries);

}