package at.gv.util.client.mms;

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.config.EgovUtilConfiguration;
import at.gv.util.ex.EgovUtilException;
import at.gv.util.wsdl.mms.GetMandatesPortType;
import at.gv.util.wsdl.mms.GetMandatesService;
import at.gv.util.wsdl.szr.SZRException;
import at.gv.util.xsd.mms.GetMandatesRequest;
import at.gv.util.xsd.mms.GetMandatesResponse;

public class MMSClient {

	@Resource
  WebServiceContext wsContext;

	private EgovUtilConfiguration config = null;
	Logger log = LoggerFactory.getLogger(MMSClient.class);
	
	public MMSClient() {}
	
	public MMSClient(EgovUtilConfiguration config) {
		if (config == null) {
			throw new NullPointerException("Parameter config must not be null.");
		}
		this.config = config;
		
		
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public GetMandatesResponse sendGetMandatesRequest(GetMandatesRequest request, String mmsServiceURL) throws SZRException, EgovUtilException {
		MiscUtil.assertNotNull(request, "request");
		MiscUtil.assertNotNull(mmsServiceURL, "mmsServiceURL");
		
		URL url = MOAIDClient.class.getResource("/wsdl/mms/mms.wsdl");
		GetMandatesService service = new GetMandatesService(url, new QName("http://reference.e-government.gv.at/namespace/mandates/mms/1.0/wsdl", "GetMandatesService"));
		GetMandatesPortType port = service.getGetMandatesPort();
		
		log.debug("MMS connection URL: " + mmsServiceURL);
		BindingProvider bindingProvider = (BindingProvider) port;
		Map<String, Object> requestContext = bindingProvider.getRequestContext();
  	requestContext.put(
        BindingProvider.ENDPOINT_ADDRESS_PROPERTY, mmsServiceURL);
		
		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 (mmsServiceURL.toLowerCase().startsWith("https")) {
    	log.trace("Using ssl for MMS client request.");
    	SSLContext sslContext = config.getMMSsslConfiguration().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.getMMSsslConfiguration().useLaxHostNameVerifier()) {
			log.trace("LaxHostnameVerifier enabled. This setting is not recommended to use.");
			tlsParams.setHostnameVerifier(new LaxHostNameVerifier());
		}
		
		http.setTlsClientParameters(tlsParams );
      }
		return port.getMandatesOperation(request);
	}
  
}