package net.sf.taverna.t2.activities.rest;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.taverna.t2.activities.rest.HTTPRequestHandler.HTTPRequestResponse;
import net.sf.taverna.t2.activities.rest.URISignatureHandler.URISignatureParsingException;
import net.sf.taverna.t2.invocation.InvocationContext;
import net.sf.taverna.t2.reference.ErrorDocument;
import net.sf.taverna.t2.reference.ReferenceService;
import net.sf.taverna.t2.reference.T2Reference;
import net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity;
import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivityCallback;

import org.apache.http.client.CredentialsProvider;
import org.apache.log4j.Logger;

import com.fasterxml.jackson.databind.JsonNode;

/**
 * Generic REST activity that is capable to perform all four HTTP methods.
 *
 * @author Sergejs Aleksejevs
 */
public class RESTActivity extends AbstractAsynchronousActivity<JsonNode> {

	public static final String URI = "http://ns.taverna.org.uk/2010/activity/rest";

	private static Logger logger = Logger.getLogger(RESTActivity.class);

	// This generic activity can deal with any of the four HTTP methods
	public static enum HTTP_METHOD {
		GET, POST, PUT, DELETE
	};

	// Default choice of data format (especially, for outgoing data)
	public static enum DATA_FORMAT {
		String(String.class), Binary(byte[].class);

		private final Class<?> dataFormat;

		DATA_FORMAT(Class<?> dataFormat) {
			this.dataFormat = dataFormat;
		}

		public Class<?> getDataFormat() {
			return this.dataFormat;
		}
	};

	// These ports are default ones; additional ports will be dynamically
	// generated from the
	// URI signature used to configure the activity
	public static final String IN_BODY = "inputBody";
	public static final String OUT_RESPONSE_BODY = "responseBody";
	public static final String OUT_RESPONSE_HEADERS = "responseHeaders";
	public static final String OUT_STATUS = "status";
	public static final String OUT_REDIRECTION = "redirection";
	public static final String OUT_COMPLETE_URL = "actualURL";

	// Configuration bean for this activity - essentially defines a particular
	// instance
	// of the activity through the values of its parameters
	private RESTActivityConfigurationBean configBean;
	private JsonNode json;

	private CredentialsProvider credentialsProvider;

	public RESTActivity(CredentialsProvider credentialsProvider) {
		this.credentialsProvider = credentialsProvider;
	}

	@Override
	public JsonNode getConfiguration() {
		return json;
	}

	public RESTActivityConfigurationBean getConfigurationBean() {
		return configBean;
	}

	@Override
	public void configure(JsonNode json) throws ActivityConfigurationException {
		this.json = json;
		configBean = new RESTActivityConfigurationBean(json);
		// Check configBean is valid - mainly check the URI signature for being
		// well-formed and
		// other details being present and valid;
		//
		// NB! The URI signature will still be valid if there are no
		// placeholders at all - in this
		// case for GET and DELETE methods no input ports will be generated and
		// a single input
		// port for input message body will be created for POST / PUT methods.
		if (!configBean.isValid()) {
			throw new ActivityConfigurationException(
					"Bad data in the REST activity configuration bean - "
							+ "possible causes are: missing or ill-formed URI signature, missing or invalid MIME types for the "
							+ "specified HTTP headers ('Accept' | 'Content-Type'). This should not have happened, as validation "
							+ "on the UI had to be performed prior to accepting this configuration.");
		}

		// (Re)create input/output ports depending on configuration
		configurePorts();
	}

	protected void configurePorts() {
		// all input ports are dynamic and depend on the configuration
		// of the particular instance of the REST activity

		// now process the URL signature - extract all placeholders and create
		// an input data type for each
		Map<String, Class<?>> activityInputs = new HashMap<>();
		List<String> placeholders = URISignatureHandler.extractPlaceholders(configBean
				.getUrlSignature());
		String acceptsHeaderValue = configBean.getAcceptsHeaderValue();
		if (acceptsHeaderValue != null && !acceptsHeaderValue.isEmpty())
			try {
				List<String> acceptsPlaceHolders = URISignatureHandler
						.extractPlaceholders(acceptsHeaderValue);
				acceptsPlaceHolders.removeAll(placeholders);
				placeholders.addAll(acceptsPlaceHolders);
			} catch (URISignatureParsingException e) {
				logger.error(e);
			}
		for (ArrayList<String> httpHeaderNameValuePair : configBean.getOtherHTTPHeaders())
			try {
				List<String> headerPlaceHolders = URISignatureHandler
						.extractPlaceholders(httpHeaderNameValuePair.get(1));
				headerPlaceHolders.removeAll(placeholders);
				placeholders.addAll(headerPlaceHolders);
			} catch (URISignatureParsingException e) {
				logger.error(e);
			}
		for (String placeholder : placeholders)
			// these inputs will have a dynamic name each;
			// the data type is string as they are the values to be
			// substituted into the URL signature at the execution time
			activityInputs.put(placeholder, String.class);

		// all inputs have now been configured - store the resulting set-up in
		// the config bean;
		// this configuration will be reused during the execution of activity,
		// so that existing
		// set-up could simply be referred to, rather than "re-calculated"
		configBean.setActivityInputs(activityInputs);

		// ---- CREATE OUTPUTS ----
		// all outputs are of depth 0 - i.e. just a single value on each;

		// output ports for Response Body and Status are static - they don't
		// depend on the configuration of the activity;
		addOutput(OUT_RESPONSE_BODY, 0);
		addOutput(OUT_STATUS, 0);
		if (configBean.getShowActualUrlPort())
			addOutput(OUT_COMPLETE_URL, 0);
		if (configBean.getShowResponseHeadersPort())
			addOutput(OUT_RESPONSE_HEADERS, 1);

		// Redirection port may be hidden/shown
		if (configBean.getShowRedirectionOutputPort())
			addOutput(OUT_REDIRECTION, 0);
	}

	/**
	 * Uses HTTP method value of the config bean of the current instance of
	 * RESTActivity.
	 *
	 * @see RESTActivity#hasMessageBodyInputPort(HTTP_METHOD)
	 */
	public boolean hasMessageBodyInputPort() {
		return hasMessageBodyInputPort(configBean.getHttpMethod());
	}

	/**
	 * Return value of this method has a number of implications - various input
	 * ports and configuration options for this activity are applied based on
	 * the selected HTTP method.
	 *
	 * @param httpMethod
	 *            HTTP method to make the decision for.
	 * @return True if this instance of the REST activity uses HTTP POST / PUT
	 *         methods; false otherwise.
	 */
	public static boolean hasMessageBodyInputPort(HTTP_METHOD httpMethod) {
		return httpMethod == HTTP_METHOD.POST || httpMethod == HTTP_METHOD.PUT;
	}

	/**
	 * This method executes pre-configured instance of REST activity. It
	 * resolves inputs of the activity and registers its outputs; the real
	 * invocation of the HTTP request is performed by
	 * {@link HTTPRequestHandler#initiateHTTPRequest(String, RESTActivityConfigurationBean, String)}
	 * .
	 */
	@Override
	public void executeAsynch(final Map<String, T2Reference> inputs,
			final AsynchronousActivityCallback callback) {
		// Don't execute service directly now, request to be run asynchronously
		callback.requestRun(new Runnable() {
			private Logger logger = Logger.getLogger(RESTActivity.class);

			@Override
			public void run() {

				InvocationContext context = callback.getContext();
				ReferenceService referenceService = context.getReferenceService();

				// ---- RESOLVE INPUTS ----

				// RE-ASSEMBLE REQUEST URL FROM SIGNATURE AND PARAMETERS
				// (just use the configuration that was determined in
				// configurePorts() - all ports in this set are required)
				Map<String, String> urlParameters = new HashMap<>();
				try {
					for (String inputName : configBean.getActivityInputs().keySet())
						urlParameters.put(inputName, (String) referenceService.renderIdentifier(
								inputs.get(inputName), configBean.getActivityInputs()
										.get(inputName), context));
				} catch (Exception e) {
					// problem occurred while resolving the inputs
					callback.fail("REST activity was unable to resolve all necessary inputs"
							+ "that contain values for populating the URI signature placeholders "
							+ "with values.", e);

					// make sure we don't call callback.receiveResult later
					return;
				}
				String completeURL = URISignatureHandler.generateCompleteURI(
						configBean.getUrlSignature(), urlParameters,
						configBean.getEscapeParameters());

				// OBTAIN THE INPUT BODY IF NECESSARY
				// ("IN_BODY" is treated as *optional* for now)
				Object inputMessageBody = null;
				if (hasMessageBodyInputPort() && inputs.containsKey(IN_BODY)) {
					inputMessageBody = referenceService.renderIdentifier(inputs.get(IN_BODY),
							configBean.getOutgoingDataFormat().getDataFormat(), context);
				}

				// ---- DO THE ACTUAL SERVICE INVOCATION ----
				HTTPRequestResponse requestResponse = HTTPRequestHandler.initiateHTTPRequest(
						completeURL, configBean, inputMessageBody, urlParameters,
						credentialsProvider);

				// test if an internal failure has occurred
				if (requestResponse.hasException()) {
					callback.fail(
							"Internal error has occurred while trying to execute the REST activity",
							requestResponse.getException());

					// make sure we don't call callback.receiveResult later
					return;
				}

				// ---- REGISTER OUTPUTS ----
				Map<String, T2Reference> outputs = new HashMap<String, T2Reference>();

				T2Reference responseBodyRef = null;
				if (requestResponse.hasServerError()) {
					// test if a server error has occurred -- if so, return
					// output as an error document

					// Check if error returned is a string - sometimes services return byte[]
					ErrorDocument errorDocument = null;
					if (requestResponse.getResponseBody() == null) {
						// No response body - register empty string
						errorDocument = referenceService.getErrorDocumentService().registerError(
								"", 0, context);
					} else {
						if (requestResponse.getResponseBody() instanceof String) {
							errorDocument = referenceService.getErrorDocumentService()
									.registerError((String) requestResponse.getResponseBody(), 0,
											context);
						} else if (requestResponse.getResponseBody() instanceof byte[]) {
							// Do the only thing we can - try to convert to
							// UTF-8 encoded string
							// and hope we'll get back something intelligible
							String str = null;
							try {
								str = new String((byte[]) requestResponse.getResponseBody(),
										"UTF-8");
							} catch (UnsupportedEncodingException e) {
								logger.error(
										"Failed to reconstruct the response body byte[]"
										+ " into string using UTF-8 encoding",
										e);
								// try with no encoding, probably will get garbage
								str = new String((byte[]) requestResponse.getResponseBody());
							}
							errorDocument = referenceService.getErrorDocumentService()
									.registerError(str, 0, context);
						} else {
							// Do what we can - call toString() method and hope
							// for the best
							errorDocument = referenceService.getErrorDocumentService()
									.registerError(requestResponse.getResponseBody().toString(), 0,
											context);
						}
					}
					responseBodyRef = referenceService.register(errorDocument, 0, true, context);
				} else if (requestResponse.getResponseBody() != null) {
					// some response data is available
					responseBodyRef = referenceService.register(requestResponse.getResponseBody(),
							0, true, context);
				} else {
					// no data was received in response to the request - must
					// have been just a response header...
					responseBodyRef = referenceService.register("", 0, true, context);
				}
				outputs.put(OUT_RESPONSE_BODY, responseBodyRef);

				T2Reference statusRef = referenceService.register(requestResponse.getStatusCode(),
						0, true, context);
				outputs.put(OUT_STATUS, statusRef);

				if (configBean.getShowActualUrlPort()) {
					T2Reference completeURLRef = referenceService.register(completeURL, 0, true,
							context);
					outputs.put(OUT_COMPLETE_URL, completeURLRef);
				}
				if (configBean.getShowResponseHeadersPort())
					outputs.put(OUT_RESPONSE_HEADERS, referenceService.register(
							requestResponse.getHeadersAsStrings(), 1, true, context));

				// only put an output to the Redirection port if the processor
				// is configured to display that port
				if (configBean.getShowRedirectionOutputPort()) {
					T2Reference redirectionRef = referenceService.register(
							requestResponse.getRedirectionURL(), 0, true, context);
					outputs.put(OUT_REDIRECTION, redirectionRef);
				}

				// return map of output data, with empty index array as this is
				// the only and final result (this index parameter is used if
				// pipelining output)
				callback.receiveResult(outputs, new int[0]);
			}
		});
	}
}
