package org.sagebionetworks.search;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.client.ClientProtocolException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.sagebionetworks.simpleHttpClient.SimpleHttpClient;
import org.sagebionetworks.simpleHttpClient.SimpleHttpClientImpl;
import org.sagebionetworks.simpleHttpClient.SimpleHttpRequest;
import org.sagebionetworks.simpleHttpClient.SimpleHttpResponse;

/**
 * CloudSearch does not yet provide a Java SDK. This is the bare minimum needed
 * for Search Updates. If we find more uses for this, we'll move it to something
 * under platform/trunk/lib.
 * 
 * @author deflaux
 * 
 */
public class CloudSearchClient {

	static private Logger logger = LogManager.getLogger(CloudSearchClient.class);
	
	private static final Map<String, String> SEND_DOCUMENTS_REQUEST_HEADERS;
	static {
		Map<String, String> requestHeaders = new HashMap<String, String>();
		requestHeaders.put("Content-Type", "application/json;charset=UTF-8");
		SEND_DOCUMENTS_REQUEST_HEADERS = Collections.unmodifiableMap(requestHeaders);
	}

	private final long MAX_BACKOFF_MS = 6400L;
	
	private SimpleHttpClient httpClient;
	private String searchServiceEndpoint;
	private String documentServiceEndpoint;

	public CloudSearchClient() {
	}
	
	public CloudSearchClient(String searchServiceEndpoint, String documentServiceEndpoint) {
		this.searchServiceEndpoint = searchServiceEndpoint;
		this.documentServiceEndpoint = documentServiceEndpoint;
	}
	
	public void _init() {
		this.httpClient = new SimpleHttpClientImpl();
	}
	
	public void setSearchServiceEndpoint(String endpoint) {
		this.searchServiceEndpoint = endpoint;
	}
	
	public String getSearchServiceEndpoint() {
		return this.searchServiceEndpoint;
	}

	public void setDocumentServiceEndpoint(String endpoint) {
		this.documentServiceEndpoint = endpoint;
	}
	
	public String getDocumentServiceEndpoint() {
		return this.documentServiceEndpoint;
	}

	public void sendDocuments(String documents) throws ClientProtocolException,
			IOException {
		SimpleHttpRequest request = new SimpleHttpRequest();
		request.setHeaders(SEND_DOCUMENTS_REQUEST_HEADERS);
		request.setUri(documentServiceEndpoint);
		httpClient.post(request, documents);
	}

	public String performSearch(String searchQuery) throws ClientProtocolException, IOException, CloudSearchClientException {
		String uri = searchServiceEndpoint + "?" + searchQuery;
		SimpleHttpRequest request = new SimpleHttpRequest();
		request.setUri(uri);
		SimpleHttpResponse response;
		long backoffMs = 100L;
		do {
			response = httpClient.get(request);
			if (response.getStatusCode() == 200) {
				return response.getContent();
			}
			if (response.getStatusCode() == 507) {
				try {
					Thread.sleep(backoffMs);
				} catch (InterruptedException e) {
					// Continue
				}
			} else {
				// rethrow
				logger.error("performSearch(): Exception rethrown (url="+(uri==null?"null":uri)+")");
				throw(new CloudSearchClientException(response.getStatusCode(), "Fail to perform search."
						+ " Reason: "+response.getStatusReason()+". Content: "+response.getContent()));
			}
			backoffMs *= 2;
		} while (backoffMs < MAX_BACKOFF_MS);
		// If we're past the max backoff, throw the last 507 we got
		if (backoffMs >= MAX_BACKOFF_MS) {
			logger.error("performSearch(): Backoff exceeded (url="+(uri==null?"null":uri)+")");
			throw(new CloudSearchClientException(response.getStatusCode(), "Fail to perform search."
					+ " Reason: "+response.getStatusReason()+". Content: "+response.getContent()));
		}
		return response.getContent();
	}
}

@@ -2910,19 +2910,37 @@
 %09%09%09%09
-// Continue
+throw new RuntimeException();
 %0A%09%09%09
@@ -3306,108 +3306,8 @@
 S);%0A
-%09%09// If we're past the max backoff, throw the last 507 we got%0A%09%09if (backoffMs %3E= MAX_BACKOFF_MS) %7B%0A%09
 %09%09lo
@@ -3390,17 +3390,16 @@
 %22)%22);%0A%09%09
-%09
 throw(ne
@@ -3479,25 +3479,24 @@
 earch.%22%0A%09%09%09%09
-%09
 + %22 Reason: 
@@ -3567,44 +3567,8 @@
 ));%0A
-%09%09%7D%0A%09%09return response.getContent();%0A
 %09%7D%0A%7D

clean up