package ua.be.wee.model.util;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublisher;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.json.JSONException;
import org.json.JSONObject;

import ua.be.wee.model.nodes.AutomatedActivity;
import ua.be.wee.service.FileStorageService;
import ua.be.wee.service.FileStorageServiceImpl;

public class HTTPRequestClient {

	public static void asyncHTTPClient(AutomatedActivity act, Map<String,Pair<String,String>> artifacts) throws JSONException {
		HttpClient httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1)
				.connectTimeout(Duration.ofMillis(act.getTimeout())).build();
		
		BodyPublisher requestBody = createJSONBody(artifacts);
		
		HttpRequest request = HttpRequest.newBuilder().uri(URI.create(act.getEndpoint()))
				.setHeader("User-Agent", "Java Async HTTPClient Example...").POST(requestBody).build();

		
		
		// sendAsync(): Sends the given request asynchronously using this client with
		// the given response body handler.
		// Equivalent to: sendAsync(request, responseBodyHandler, null).
		CompletableFuture<HttpResponse<String>> asyncResponse = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());

		String asyncResultBody = null;
		int asyncResultStatusCode = 0;
		try {
			//asyncResponse.thenRun(() -> System.out.println());
			asyncResultBody = asyncResponse.thenApply(HttpResponse::body).get(act.getTimeout(), TimeUnit.MILLISECONDS);

			// OR:

			// join(): Returns the result value when complete, or throws an (unchecked)
			// exception if completed exceptionally.
			// To better conform with the use of common functional forms,
			// if a computation involved in the completion of this CompletableFuture threw
			// an exception,
			// this method throws an (unchecked) CompletionException with the underlying
			// exception as its cause.

			//HttpResponse<String> response = asyncResponse.join();
			asyncResultStatusCode = asyncResponse.thenApply(HttpResponse::statusCode).get(act.getTimeout(), TimeUnit.MILLISECONDS);
		} catch (InterruptedException | ExecutionException | TimeoutException e) {
			e.printStackTrace();
		}
		System.out.println("=============== AsyncHTTPClient Body:===============  \n" + asyncResultBody);
		System.out.println(
				"\n=============== AsyncHTTPClient Status Code:===============  \n" + asyncResultStatusCode);
	}



	private static BodyPublisher createJSONBody(Map<String,Pair<String,String>> params) throws JSONException {
		JSONObject body = new JSONObject();
		JSONObject input = new JSONObject();
		Set<String> keySet = params.keySet();
		for (String dataPort : keySet) {
			JSONObject inner = new JSONObject();
			inner.put("type", "inline");
			inner.put("content", params.get(dataPort).getSnd());
			input.put(dataPort, inner);
		}
		body.put("input", input);
		System.out.println(body.toString());
		return HttpRequest.BodyPublishers.ofString(body.toString());
	}


	public static void main(String[] args) throws JSONException {
		

		FileStorageService storageService = new FileStorageServiceImpl();
		storageService.setStorageURL("http://localhost:5000");
				
		AutomatedActivity a = new AutomatedActivity();
		a.setTimeout(5000);
		a.setEndpoint("http://localhost:7999");
		
		Map<String,Pair<String,String>> params = new HashMap<String, Pair<String,String>>();
				
		String content = storageService.load("mock_requirements.txt");
		System.out.println(content);
		params.put("din", new Pair<String, String>("txt", content));
		
		asyncHTTPClient(a, params);
		System.out.println("chegou aqui");

	}

}
