package at.gv.util.client.mis;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.Handler;

import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import at.gv.util.LaxHostNameVerifier;
import at.gv.util.LoggingHandler;
import at.gv.util.MiscUtil;
import at.gv.util.client.moaid.MOAIDClient;
import at.gv.util.client.szr.SZRClient;
import at.gv.util.config.EgovUtilConfiguration;
import at.gv.util.ex.EgovUtilException;
import at.gv.util.wsdl.mis.MandateIssuePortType;
import at.gv.util.wsdl.mis.MandateIssueService;
import at.gv.util.wsdl.szr.SZRException;
import at.gv.util.xsd.mis.MandateIssueRequestType;
import at.gv.util.xsd.mis.MandateIssueResponseType;

public class MISClient {

	@Resource
  WebServiceContext wsContext;

	private EgovUtilConfiguration config = null;
	Logger log = LoggerFactory.getLogger(MISClient.class);
	
	public MISClient() {}
	
	public MISClient(EgovUtilConfiguration config) {
		if (config == null) {
			throw new NullPointerException("Parameter config must not be null.");
		}
		this.config = config;
		
		
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public MandateIssueResponseType sendMandateIssueRequest(MandateIssueRequestType mir, String misServiceURL) throws SZRException, EgovUtilException {
		MiscUtil.assertNotNull(mir, "mir");
		MiscUtil.assertNotNull(misServiceURL, "misServiceURL");
		
		URL url = SZRClient.class.getResource("/wsdl/mis/mis-1.0.3.wsdl");
		MandateIssueService service = new MandateIssueService(url, new QName("http://reference.e-government.gv.at/namespace/mandates/mis/1.0/wsdl", "MandateIssueService"));
		MandateIssuePortType port = service.getMandateIssuePort();
		
		log.debug("MIS connection URL: " + misServiceURL);
		BindingProvider bindingProvider = (BindingProvider) port;
		Map<String, Object> requestContext = bindingProvider.getRequestContext();
  	requestContext.put(
        BindingProvider.ENDPOINT_ADDRESS_PROPERTY, misServiceURL);
		
		log.trace("Adding JAX-WS request/response trace handler.");
  	List<Handler> handlerList = bindingProvider.getBinding().getHandlerChain();
  	if (handlerList == null) {
      handlerList = new ArrayList();
    }
    LoggingHandler loggingHandler = new LoggingHandler();
    handlerList.add(loggingHandler);
    bindingProvider.getBinding().setHandlerChain(handlerList);

    // check for ssl
		if (misServiceURL.toLowerCase().startsWith("https")) {
    	log.trace("Using ssl for MIS client request.");
    	SSLContext sslContext = config.getMISsslConfiguration().getSSLContext(false);
    	if (sslContext == null) {
				throw new EgovUtilException("SSL context from configuration is empty. Please configure an SSL context in the configuration first.");
			}
		Client client = ClientProxy.getClient(port);
		HTTPConduit http = (HTTPConduit) client.getConduit();
		HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
		 
		httpClientPolicy.setConnectionTimeout(36000);
		httpClientPolicy.setAllowChunking(false);
		httpClientPolicy.setReceiveTimeout(32000);
		 
		http.setClient(httpClientPolicy);
		
		TLSClientParameters tlsParams = new TLSClientParameters();			
		tlsParams.setSSLSocketFactory(sslContext.getSocketFactory());
					
		// check for lax hostname
		if (this.config.getMISsslConfiguration().useLaxHostNameVerifier()) {
			log.trace("LaxHostnameVerifier enabled. This setting is not recommended to use.");
			tlsParams.setHostnameVerifier(new LaxHostNameVerifier());
		}
		
		http.setTlsClientParameters(tlsParams );
    }
		return port.mandateIssueOperation(mir);
	}
  
}