package io.vertx.examples.feeds.verticles;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Context;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.examples.feeds.utils.async.MultipleFutures;

import java.util.ArrayList;
import java.util.List;

/**
 * Main verticle, orchestrate the instanciation of other verticles
 */
public class MainVerticle extends AbstractVerticle {

	public static final int REDIS_PORT = 8888;
	public static final int MONGO_PORT = 8889;

	private List<String> deploymentIds;

	@Override
	public void init(Vertx vertx, Context context) {
		super.init(vertx, context);
		deploymentIds = new ArrayList<String>(3);
	}

	@Override
	public void start(Future<Void> future) {
		deployEmbeddedDbs(future, this::deployFeedBroker);
	}

	private void deployEmbeddedDbs(Future<Void> future, Handler<Future<Void>> whatsNext) {
		MultipleFutures dbDeployments = new MultipleFutures();
		dbDeployments.add(this::deployEmbeddedRedis);
		dbDeployments.add(this::deployEmbeddedMongo);
		dbDeployments.setHandler(result -> {
			if (result.failed()) {
				future.fail(result.cause());
			} else {
				whatsNext.handle(future);
			}
		});
		dbDeployments.start();
	}

	private void deployEmbeddedRedis(Future<Void> future) {
		DeploymentOptions options = new DeploymentOptions();
		options.setWorker(true);
		vertx.deployVerticle(EmbeddedRedis.class.getName(), options, result -> {
			if (result.failed()) {
				future.fail(result.cause());
			} else {
				future.complete();
			}
		});
	}

	private void deployEmbeddedMongo(Future<Void> future) {
		DeploymentOptions options = new DeploymentOptions();
		options.setWorker(true);
		vertx.deployVerticle(EmbeddedMongo.class.getName(), options, result -> {
			if (result.failed()) {
				future.fail(result.cause());
			} else {
				future.complete();
			}
		});
	}

	private void deployFeedBroker(Future<Void> future) {
		JsonObject dbConfig = new JsonObject();
		dbConfig.put("redis", redisConfig());
		dbConfig.put("mongo", mongoConfig());
		DeploymentOptions brokerOptions = new DeploymentOptions();
		brokerOptions.setConfig(dbConfig);
		vertx.deployVerticle(FeedBroker.class.getName(), brokerOptions, brokerResult -> {
			if (brokerResult.failed()) {
				future.fail(brokerResult.cause());
			} else {
				deploymentIds.add(brokerResult.result());
				DeploymentOptions webserverOptions = new DeploymentOptions();
				webserverOptions.setConfig(dbConfig);
				vertx.deployVerticle(WebServer.class.getName(), webserverOptions, serverResult -> {
					if (serverResult.failed()) {
						future.fail(serverResult.cause());
					} else {
						deploymentIds.add(serverResult.result());
						future.complete();
					}
				});
			}
		});
	}

	@Override
	public void stop(Future<Void> future) {
		deploymentIds.forEach(deploymentId -> {
			vertx.undeploy(deploymentId);
		});
	}

	private JsonObject mongoConfig() {
		JsonObject config = new JsonObject();
		config.put("host", "localhost");
		config.put("port", MONGO_PORT);
		config.put("db_name", "vertx-feeds");
		return config;
	}

	private JsonObject redisConfig() {
		JsonObject config = new JsonObject();
		config.put("host", "localhost");
		config.put("port", REDIS_PORT);
		return config;
	}
}

@@ -2889,80 +2889,400 @@
 %7B%0A%09%09
-deploymentIds.forEach(deploymentId -%3E %7B%0A%09%09%09vertx.undeploy(deploymentId);
+MultipleFutures futures = new MultipleFutures(future);%0A%09%09deploymentIds.forEach(deploymentId -%3E %7B%0A%09%09%09futures.add(fut -%3E %7B%0A%09%09%09%09undeploy(deploymentId, fut);%0A%09%09%09%7D);%0A%09%09%7D);%0A%09%09futures.start();%0A%09%7D%0A%0A%09private void undeploy(String deploymentId, Future%3CVoid%3E future) %7B%0A%09%09vertx.undeploy(deploymentId, res -%3E %7B%0A%09%09%09if (res.succeeded()) %7B%0A%09%09%09%09future.complete();%0A%09%09%09%7D else %7B%0A%09%09%09%09future.fail(res.cause());%0A%09%09%09%7D
 %0A%09%09%7D

stop properly