package org.gcube.application.geoportal.client.plugins;

import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.gcube.application.geoportal.client.DefaultDocumentsClient;
import org.gcube.application.geoportal.client.utils.Serialization;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.rest.InterfaceConstants;
import org.gcube.application.geoportal.common.rest.Projects;
import org.gcube.common.calls.jaxrs.GcubeService;
import org.gcube.common.calls.jaxrs.TargetFactory;
import org.gcube.common.clients.config.ProxyConfig;
import org.gcube.common.clients.delegates.ProxyDelegate;
import org.w3c.dom.Node;

import javax.ws.rs.client.WebTarget;
import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMResult;
import javax.xml.ws.EndpointReference;

@Slf4j
@RequiredArgsConstructor
public class ProjectsInterfacePlugin<C extends DefaultDocumentsClient,P extends Project> extends GeoportalAbstractPlugin<WebTarget, Projects<P>>{
	
	@NonNull
	private String profileID;

	@Setter
	private Class<C> customClientImplementation= (Class<C>) DefaultDocumentsClient.class;

	@Setter
	private Class<P> profiledModel= (Class<P>) Project.class;

	@Override
	public Exception convert(Exception fault, ProxyConfig<?, ?> config) {
		return fault;
	}

	@SneakyThrows //no such constructor
	@Override
	public Projects<P> newProxy(ProxyDelegate<WebTarget> delegate) {
		return customClientImplementation.getConstructor(ProxyDelegate.class,String.class,Class.class).
					newInstance(delegate,profileID,profiledModel);
	}
	
	@Override
	public WebTarget resolve(EndpointReference address, ProxyConfig<?, ?> config) throws Exception {
		DOMResult result = new DOMResult();
		address.writeTo(result);
		Node node =result.getNode();
		Node child=node.getFirstChild();
		String addressString = child.getTextContent();
		GcubeService service = GcubeService.service().
				withName(new QName(InterfaceConstants.NAMESPACE,InterfaceConstants.Methods.PROJECTS)).
				andPath(InterfaceConstants.Methods.PROJECTS);
		WebTarget target = TargetFactory.stubFor(service).at(addressString);
		//Registering provider
		JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
		provider.setMapper(Serialization.mapper);
		target.register(provider);

		return target;
	}
}
