package eu.dnetlib.clients.msro;

import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import eu.dnetlib.clients.BaseServiceClient;
import eu.dnetlib.enabling.annotations.DnetServiceClient;
import eu.dnetlib.enabling.annotations.DnetServiceType;
import eu.dnetlib.exceptions.DnetGenericException;
import eu.dnetlib.msro.workflows.WorkflowRef;
import eu.dnetlib.msro.workflows.logs.WfLogEntry;
import eu.dnetlib.services.async.AsyncClientCallback;
import eu.dnetlib.services.async.AsyncClientUtils;

@Component
@Scope("prototype")
@DnetServiceClient(DnetServiceType.msro)
public class MsroClient extends BaseServiceClient {

	@Autowired
	private AsyncClientUtils asyncClientUtils;

	public WorkflowRef startWorkflow(final String wfId) {
		return startWorkflow(wfId, (String) null, (String) null, (String) null);
	}

	public WorkflowRef startWorkflow(final String wfId, final String parent) {
		return startWorkflow(wfId, parent, (String) null, (String) null);
	}

	public WorkflowRef startWorkflow(final String wfId, final String parent, final String dsId, final String ifaceId) {
		final StringWriter url = new StringWriter();

		url.append(getBaseUrl());
		url.append("/startWorkflow?wfId=");
		url.append(wfId);

		if (StringUtils.isNotBlank(parent)) {
			url.append("&parent=");
			url.append(parent);
		}
		if (StringUtils.isNotBlank(dsId)) {
			url.append("&dsId=");
			url.append(dsId);
		}
		if (StringUtils.isNotBlank(ifaceId)) {
			url.append("&ifaceId=");
			url.append(ifaceId);
		}

		return (new RestTemplate()).getForObject(url.toString(), WorkflowRef.class);
	}

	public WorkflowRef startRepoHiWorkflow(final String wfId, final String workerId, final String dsId, final String iface) throws DnetGenericException {
		final StringWriter url = new StringWriter();

		url.append(getBaseUrl());
		url.append("/startRepoHiWorkflow");

		if (StringUtils.isNotBlank(wfId)) {
			url.append("?wfId=");
			url.append(wfId);
		} else {
			throw new DnetGenericException("Missing wfId");
		}

		if (StringUtils.isNotBlank(workerId)) {
			url.append("&workerId=");
			url.append(workerId);
		} else {
			throw new DnetGenericException("Missing workerId");
		}
		if (StringUtils.isNotBlank(dsId)) {
			url.append("&dsId=");
			url.append(dsId);
		} else {
			throw new DnetGenericException("Missing dsId");
		}
		if (StringUtils.isNotBlank(iface)) {
			url.append("&iface=");
			url.append(iface);
		} else {
			throw new DnetGenericException("Missing iface");
		}

		return (new RestTemplate()).getForObject(url.toString(), WorkflowRef.class);
	}

	public WorkflowRef startRepoByeForWorkflow(final String wfId) throws DnetGenericException {
		final StringWriter url = new StringWriter();

		url.append(getBaseUrl());
		url.append("/startRepoByeWorkflow");

		if (StringUtils.isNotBlank(wfId)) {
			url.append("?wfId=");
			url.append(wfId);
		} else {
			throw new DnetGenericException("Missing wfId");
		}

		return (new RestTemplate()).getForObject(url.toString(), WorkflowRef.class);
	}

	public void startWorkflow(final String wfId, final String parent, final String localBaseUrl, final AsyncClientCallback callback) {
		final Workflow wf = new Workflow(wfId, parent, null);
		asyncClientUtils.invokeRemoteMethod(getBaseUrl(), "startWorkflow", localBaseUrl, wf, callback);
	}

	public void startWorkflow(final String wfId,
			final String parent,
			final String dsId,
			final String ifaceId,
			final String localBaseUrl,
			final AsyncClientCallback callback) {
		final Workflow wf = new Workflow(wfId, parent, dsId, ifaceId, null);
		asyncClientUtils.invokeRemoteMethod(getBaseUrl(), "startWorkflow", localBaseUrl, wf, callback);
	}

	public List<WfLogEntry> listWfLogs(final String wfId) {
		final RestTemplate restTemplate = new RestTemplate();
		final String url = getBaseUrl() + "/logs?wfId=" + wfId;
		return Arrays.asList(restTemplate.getForObject(url, WfLogEntry[].class));
	}

	public WorkflowRef startWorkflowTemplate(final String node, final String parent) {
		final StringWriter url = new StringWriter();
		url.append(getBaseUrl());
		url.append("/startWorkflowTemplate?parent=");
		url.append(parent);
		url.append("&node=");
		url.append(node);
		return (new RestTemplate()).getForObject(url.toString(), WorkflowRef.class);
	}

	public void startWorkflowTemplate(final WorkflowTemplate wf, final String localBaseUrl, final AsyncClientCallback callback) {
		asyncClientUtils.invokeRemoteMethod(getBaseUrl(), "startWorkflowTemplate", localBaseUrl, wf, callback);
	}

}
