package cz.senslog.analytics.module.api;

import cz.senslog.analytics.domain.ThresholdViolationAlert;
import cz.senslog.analytics.module.AlertModule;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.eventbus.EventBus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public abstract class SimpleModule extends AbstractVerticle implements ModuleDescriptor {

    private static final Logger logger = LogManager.getLogger(SimpleModule.class);

    protected abstract void configure(Promise<Void> completePromise);

    protected abstract void run(Promise<Void> completePromise);

    public final Future<Void> reconfigure() {
        Promise<Void> configPromise = Promise.promise();
        logger.info("Reconfiguration of the module: {}", getClass().getSimpleName());
        configure(configPromise);
        return configPromise.future();
    }

    @Override
    public final String id() {
        return String.format("__module.%s", getClass().getSimpleName());
    }


    @Override
    public void start(Promise<Void> startPromise) {
        logger.info("Start of the module: {}", getClass().getSimpleName());
        Promise<Void> configPromise = Promise.promise();
        logger.info("Configuration of the module: {}", getClass().getSimpleName());
        configure(configPromise);
        configPromise.future().compose(v -> {
                    Promise<Void> p = Promise.promise();
                    logger.info("Running the module: {}", getClass().getSimpleName());
                    run(p);
                    return p.future();
                })
                .onSuccess(startPromise::complete)
                .onFailure(startPromise::fail);

    }

    protected final EventBus eventBus() {
        return vertx.eventBus();
    }

    protected final void notify(ThresholdViolationAlert notification) {
        eventBus().publish(Module.of(AlertModule.class).id(), notification);
    }
}