package at.gv.egovernment.moa.spss.server.webservice.impl;

import java.util.ResourceBundle;

import javax.annotation.Resource;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;

import org.apache.cxf.binding.soap.Soap12;
import org.apache.cxf.binding.soap.SoapFault;
import org.apache.cxf.common.i18n.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import at.gv.egiz.moasig.VerifyCMSSignatureRequest;
import at.gv.egiz.moasig.VerifyCMSSignatureResponseType;
import at.gv.egiz.moasig.VerifyPDFSignatureRequest;
import at.gv.egiz.moasig.VerifyPDFSignatureResponseType;
import at.gv.egiz.moasig.VerifyXMLSignatureRequest;
import at.gv.egiz.moasig.VerifyXMLSignatureResponseType;
import at.gv.egovernment.moa.spss.MOAException;
import at.gv.egovernment.moa.spss.MOASystemException;
import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker;
import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureVerificationInvoker;
import at.gv.egovernment.moa.spss.server.webservice.CMSVerifySignatureBinding;
import at.gv.egovernment.moa.spss.server.webservice.SignatureVerificationService;
import at.gv.egovernment.moa.spss.server.webservice.XMLVerifySignatureBinding;
import at.gv.egovernment.moa.spss.server.webservice.binding.CMSVerifySignatureBindingImpl;
import at.gv.egovernment.moa.spss.server.webservice.binding.XMLVerifySignatureBindingImpl;
import at.gv.egovernment.moa.util.StreamUtils;

@WebService(endpointInterface = "at.gv.egovernment.moa.spss.server.webservice.SignatureVerificationService", portName = "SignatureVerificationService", serviceName = "SignatureVerificationService")
public class SignatureVerificationServiceImpl implements SignatureVerificationService {

	private static final Logger logger = LoggerFactory.getLogger(SignatureVerificationServiceImpl.class);

	@Resource
	private WebServiceContext context;

	private XMLVerifySignatureBinding xmlVerifySignatureBinding;
	private CMSVerifySignatureBinding cmsVerifySignatureBinding;

	public SignatureVerificationServiceImpl() {
		this.xmlVerifySignatureBinding = new XMLVerifySignatureBindingImpl();
		this.cmsVerifySignatureBinding = new CMSVerifySignatureBindingImpl();
	}

	@Override
	@WebResult(name = "VerifyXMLSignatureResponseType", targetNamespace = "http://reference.e-government.gv.at/namespace/moa/20151109#")
	public VerifyXMLSignatureResponseType verifyXMLSignature(VerifyXMLSignatureRequest verifyXMLSignatureRequest)
			throws Exception {
		logger.info("verifyXMLSignature start");
		try {
			logger.info("WebServiceContext: {}", context);
			ContextSetupAspect.setupContext(context.getMessageContext(), "verifyXMLSignature");

			XMLSignatureVerificationInvoker invoker = XMLSignatureVerificationInvoker.getInstance();

			at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest requestObj;
			at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse responseObj;

			logger.trace(">>> preparsing Request");
			requestObj = this.xmlVerifySignatureBinding.buildXMLRequest(verifyXMLSignatureRequest);
			logger.trace("<<< preparsed Request");

			logger.trace(">>> verifying Signature");
			// invoke the core logic
			responseObj = invoker.verifyXMLSignature(requestObj);
			logger.trace("<<< verified Signature");

			logger.trace(">>> building Response");
			// map back to XML
			VerifyXMLSignatureResponseType response = this.xmlVerifySignatureBinding.buildXMLResponse(responseObj);
			logger.trace("<<< built Response");
			
			return response;
		} catch (MOAException e) {
			SoapFault soapFault = SoapFault.createFault(new org.apache.cxf.interceptor.Fault(
					new Message(e.getMessage(), (ResourceBundle)null)), 
					Soap12.getInstance());
			soapFault.setDetail(e.toErrorResponse());
		      
			logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" 
		        + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e));
		      throw soapFault;
		} catch (Throwable t) {
			MOASystemException e = new MOASystemException("2900", null, t);
			logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:"
					+ System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e));
			logger.error("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:", e);
			throw new Exception(e.getMessage());
		} finally {
			ContextSetupAspect.cleanContext();
		}
	}

	@Override
	@WebResult(name = "VerifyCMSSignatureResponseType", targetNamespace = "http://reference.e-government.gv.at/namespace/moa/20151109#")
	public VerifyCMSSignatureResponseType verifyCMSSignature(VerifyCMSSignatureRequest verifyCMSSignatureRequest)
			throws Exception {
		logger.info("verifyCMSSignature start");
		try {
			logger.info("WebServiceContext: {}", context);
			ContextSetupAspect.setupContext(context.getMessageContext(), "verifyCMSSignature");

			CMSSignatureVerificationInvoker invoker = CMSSignatureVerificationInvoker.getInstance();

			at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest requestObj;
			at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse responseObj;

			logger.trace(">>> preparsing Request");
			requestObj = this.cmsVerifySignatureBinding.buildCMSRequest(verifyCMSSignatureRequest);
			logger.trace("<<< preparsed Request");

			logger.trace(">>> verifying Signature");
			// invoke the core logic
			responseObj = invoker.verifyCMSSignature(requestObj);
			logger.trace("<<< verified Signature");

			logger.trace(">>> building Response");
			// map back to XML
			VerifyCMSSignatureResponseType response = this.cmsVerifySignatureBinding.buildCMSResponse(responseObj);
			logger.trace("<<< built Response");

			return response;
		} catch (MOAException e) {
			SoapFault soapFault = SoapFault.createFault(new org.apache.cxf.interceptor.Fault(
					new Message(e.getMessage(), (ResourceBundle)null)), 
					Soap12.getInstance());
			soapFault.setDetail(e.toErrorResponse());
		      
			logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" 
		        + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e));
		      throw soapFault;
		} catch (Throwable t) {
			MOASystemException e = new MOASystemException("2900", null, t);
			logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:"
					+ System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e));
			logger.error("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:", e);
			throw new Exception(e.getMessage());
		} finally {
			ContextSetupAspect.cleanContext();
		}
	}
	
	@Override
	@WebResult(name = "VerifyPDFSignatureResponseType", targetNamespace = "http://reference.e-government.gv.at/namespace/moa/20151109#")
	public VerifyPDFSignatureResponseType verifyPDFSignature(VerifyPDFSignatureRequest verifyPDFSignatureRequest)
			throws Exception {
		logger.info("verifyPDFSignature start");
		try {
			logger.info("WebServiceContext: {}", context);
			ContextSetupAspect.setupContext(context.getMessageContext(), "verifyPDFSignature");
			
			CMSSignatureVerificationInvoker invoker = CMSSignatureVerificationInvoker.getInstance();

			at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest requestObj;
			at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse responseObj;

			logger.trace(">>> preparsing Request");
			requestObj = this.cmsVerifySignatureBinding.buildPDFRequest(verifyPDFSignatureRequest);
			logger.trace("<<< preparsed Request");
			
			logger.trace(">>> verifying Signature");
			// invoke the core logic
			responseObj = invoker.verifyCMSSignature(requestObj);
			logger.trace("<<< verified Signature");

			logger.trace(">>> building Response");
			// map back to XML
			VerifyPDFSignatureResponseType response = this.cmsVerifySignatureBinding.buildPDFResponse(responseObj);
			logger.trace("<<< built Response");

			return response;
		} catch (MOAException e) {
			SoapFault soapFault = SoapFault.createFault(new org.apache.cxf.interceptor.Fault(
					new Message(e.getMessage(), (ResourceBundle)null)), 
					Soap12.getInstance());
			soapFault.setDetail(e.toErrorResponse());
		      
			logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" 
		        + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e));
		      throw soapFault;
		} catch (Throwable t) {
			MOASystemException e = new MOASystemException("2900", null, t);
			logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:"
					+ System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e));
			logger.error("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:", e);
			throw new Exception(e.getMessage());
		} finally {
			ContextSetupAspect.cleanContext();
		}
	}

}