package ankurm.sc;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

import com.sun.net.httpserver.HttpServer;

import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.config.monitor.HttpPropertyPathNotifier;
import org.springframework.cloud.config.monitor.MonitorConfigurationProperties;
import org.springframework.web.client.RestClient;

/**
 * Spring Cloud Config 5.1.0-M1: what does HttpPropertyPathNotifier send when Config Server sees "orders" changed?
 * A JDK HttpServer plays the client application; a stub DiscoveryClient says where it lives.
 */
public class HttpNotifierDemo {

	public static void main(String[] args) throws Exception {
		List<String> received = new CopyOnWriteArrayList<>();
		HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
		server.createContext("/", ex -> {
			received.add(ex.getRequestMethod() + " " + ex.getRequestURI());
			ex.sendResponseHeaders(204, -1);
			ex.close();
		});
		server.start();
		int port = server.getAddress().getPort();

		DefaultServiceInstance defaultPath = new DefaultServiceInstance("i1", "orders", "127.0.0.1", port, false);
		DefaultServiceInstance metaPath = new DefaultServiceInstance("i2", "orders", "127.0.0.1", port, false,
				Map.of("refresh-endpoint", "/custom/refresh"));
		DefaultServiceInstance dead = new DefaultServiceInstance("i3", "orders", "127.0.0.1", 1, false);
		DiscoveryClient discovery = new DiscoveryClient() {
			public String description() { return "stub"; }
			public List<ServiceInstance> getInstances(String id) {
				return "orders".equals(id) ? List.of(defaultPath, metaPath, dead) : List.of();
			}
			public List<String> getServices() { return List.of("orders"); }
		};

		MonitorConfigurationProperties props = new MonitorConfigurationProperties();
		HttpPropertyPathNotifier notifier = new HttpPropertyPathNotifier(discovery, RestClient.builder().build(), props);

		System.out.println("== 1. changed applications: orders and ghost");
		notifier.notifyApplications(Set.of("orders", "ghost"));
		received.stream().sorted().forEach(r -> System.out.println("server received: " + r));
		System.out.println("requests received = " + received.size() + " (3 instances registered for orders, one unreachable)");

		System.out.println("== 2. override the path per application");
		received.clear();
		props.getHttp().setEndpoints(Map.of("orders", "/internal/refresh"));
		notifier.notifyApplications(Set.of("orders"));
		received.stream().sorted().forEach(r -> System.out.println("server received: " + r));
		server.stop(0);
	}
}
