package aQute.bnd.repository.maven.provider;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.osgi.util.promise.Promise;
import org.osgi.util.promise.PromiseFactory;

import aQute.bnd.http.HttpClient;
import aQute.libg.glob.Glob;

class Crawler {
	private final static Pattern	HREF_P	= Pattern.compile("href\\s*=\\s*\"(?<uri>[^\"]+)\"",
		Pattern.CASE_INSENSITIVE);

	final PromiseFactory			pf;
	final HttpClient				client;

	public Crawler(HttpClient client, PromiseFactory pf) {
		this.client = client;
		this.pf = pf;
	}

	public List<URI> getURIs(URI uri, Predicate<URI> predicate) throws Exception {
		assert uri != null;
		assert predicate != null;

		String page = client.build()
			.get(String.class)
			.go(uri);

		List<Promise<List<URI>>> promises = new ArrayList<>();
		List<URI> uris = new ArrayList<>();

		Matcher m = HREF_P.matcher(page);
		while (m.find()) {
			String path = m.group("uri");
			URI next = uri.resolve(path)
				.normalize();

			if (next.getPath()
				.endsWith("/")) {

				URI relativize = uri.relativize(next);
				if (relativize.isAbsolute())
					continue; // not recursive, points outside

				Promise<List<URI>> downstream = pf.submit(() -> getURIs(next, predicate));
				promises.add(downstream);
			} else {
				if (predicate.test(next))
					uris.add(next);
			}
		}
		for (Promise<List<URI>> p : promises) {
			uris.addAll(p.getValue());
		}
		return uris;
	}

	public List<URI> getURIs(URI uri) throws Exception {
		return getURIs(uri, u -> true);
	}

	public static Predicate<URI> predicate(String include, String exclude) {
		Glob i = include == null ? Glob.ALL : new Glob(include);
		Glob e = exclude == null ? Glob.NONE : new Glob(exclude);

		return uri -> {
			String path = uri.getPath();
			return i.matcher(path)
				.find()
				&& !e.matcher(path)
					.find();
		};
	}



}

@@ -353,20 +353,23 @@
 bg.glob.
-Glob
+PathSet
 ;%0A%0Aclass
@@ -1710,54 +1710,47 @@
 %7B%0A%09%09
-Glob i = include == null ? Glob.ALL : new Glob
+PathSet pathSet = new PathSet().include
 (inc
@@ -1758,59 +1758,20 @@
 ude)
-;
 %0A%09%09
-Glob e = exclude == null ? Glob.NONE : new Glob
+%09.exclude
 (exc
@@ -1781,60 +1781,55 @@
 e);%0A
-%0A
 %09%09
+P
 re
-turn uri -%3E %7B%0A%09%09%09String path = uri.getPath(
+dicate%3CString%3E find = pathSet.find(%22**%22
 );%0A
-%09
 %09%09re
@@ -1837,83 +1837,42 @@
 urn 
-i.matcher(path)%0A%09%09%09%09.find()%0A%09%09%09%09&& !e.matcher(path)%0A%09%09%09%09%09.find(
+uri -%3E find.test(uri.getPath()
 );%0A
-%09
 %09%7D
-;%0A%09%7D%0A%0A%0A
 %0A%7D%0A

Use PathSet.find to build include/exclude predicate