package spring.verticles;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.handler.BodyHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class ProxyVerticle extends AbstractVerticle {

    @Value(value = "${http.port}")
    private int httpPort;

    @Value(value = "${tdg.port}")
    private int tdgPort;

    @Value(value = "${server.host}")
    private String serverHost;

    private Router router;


    @Override
    public void start() throws Exception {
        super.start();
        this.router = Router.router(vertx);
        createHttpServer();
        bodyHandlerEnabler();
        buildPostRoute();
    }

    private void bodyHandlerEnabler() {
        router.route().handler(BodyHandler.create());
    }

    private void createHttpServer() {
        vertx.createHttpServer()
                .requestHandler(router)
                .listen(httpPort);
    }

    private void buildPostRoute() {
        router.post("/post")
                .handler(rc -> {
                    this.graphql(rc.getBodyAsJson())
                            .onSuccess(httpResp -> {
                                if (httpResp.statusCode() == 200) {
                                    rc.end(httpResp.bodyAsBuffer());
                                }
                            });
                });
    }

    private Future<HttpResponse<Buffer>> graphql(JsonObject request) {
        Promise<HttpResponse<Buffer>> promise = Promise.promise();
        WebClient.create(vertx)
                .post(tdgPort, serverHost, "/graphql")
                .putHeader("Content-Type", "application/json")
                .sendJson(request, t -> {
                    if (t.succeeded()) {
                        promise.complete(t.result());
                    }
                });
        return promise.future();
    }
}
