package simulator.interfaces.rest;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;

import models.algebra.Constant;
import models.algebra.Expression;
import models.algebra.Term;
import models.dataConstraintModel.DataConstraintModel;
import models.dataConstraintModel.JsonTerm;
import models.dataConstraintModel.MapTerm;
import models.dataConstraintModel.ResourcePath;
import models.dataFlowModel.DataTransferChannel;
import simulator.Resource;
import simulator.Simulator;
import simulator.interfaces.NativeSender;

public class ResponseSender extends NativeSender{
	
	private HttpClient client;
	private HttpRequest request;

	public ResponseSender(Simulator simulator, DataTransferChannel channel, ResourcePath resourcePath,
			Resource resource, String url, String method, MapTerm header, JsonTerm body) {
		super(simulator, channel, resourcePath, resource);
		client = HttpClient.newHttpClient();
		HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
				.uri(URI.create(url));
		
		for(String key : header.keySet()) {
			requestBuilder.header(key, header.get(key).toString());
		}
		
		switch(method) {
		case "GET":
			request = requestBuilder
				.GET()
				.build();
			break;
		case "POST":
			request = requestBuilder
				.POST(BodyPublishers.ofString(body.toString()))
				.build();
			break;
		default:
			request = requestBuilder
				.GET()
				.build();
		}
	}
	
	public void sendRequest() {
		CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
		responseFuture.thenAccept(response -> {
			sendResponse(response.body());
		}).exceptionally(e -> {
			e.printStackTrace();
			return null;
		});
	}
	
	private void sendResponse(String response) {
		Constant res = new Constant(response, DataConstraintModel.typeString);
		Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression();
		message = (Term)message.clone();
		((Term) message).setChild(0, res);
		sendToModel(message);
	}

}
