package com.ejie.ad74a.util.webservice;

import java.util.HashSet;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WsseClientHandler implements SOAPHandler<SOAPMessageContext> {

	/**
	 * Final static logger.
	 */
	private static final Logger logger = LoggerFactory.getLogger(WsseClientHandler.class);

	private static final String SECURITY_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
	private static final String PASSWORD_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
	private static final String AUTH_PREFIX = "wss";

	private String usrKey = "";
	private String usrPwd = "";

	public WsseClientHandler() {
		// TODO ¿?¿?
		this.usrKey = "xc017";
		this.usrPwd = "televida";
	}

	public WsseClientHandler(String usrKey, String usrPwd) {
		this.usrKey = usrKey;
		this.usrPwd = usrPwd;
	}

	@Override
	public boolean handleMessage(final SOAPMessageContext msgCtx) {
		// Indicator telling us which direction this message is going in
		final Boolean outInd = (Boolean) msgCtx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
		// Handler must only add security headers to outbound messages
		if (outInd.booleanValue()) {
			try {
				if (null != usrKey && usrKey.length() > 0 && null != usrPwd) {
					// HTTP basic security
					msgCtx.put(BindingProvider.USERNAME_PROPERTY, usrKey);
					msgCtx.put(BindingProvider.PASSWORD_PROPERTY, usrPwd);
					// WSS-security PasswordText
					final SOAPEnvelope envelope = msgCtx.getMessage().getSOAPPart().getEnvelope();
					SOAPHeader header = envelope.getHeader();
					if (header == null) {
						header = envelope.addHeader();
					}
					final SOAPElement seSecurity = header.addChildElement("Security", AUTH_PREFIX, SECURITY_NS);
					final SOAPElement seUserToken = seSecurity.addChildElement("UsernameToken", AUTH_PREFIX);
					final SOAPElement seUserName = seUserToken.addChildElement("Username", AUTH_PREFIX);
					final SOAPElement seUserPwd = seUserToken.addChildElement("Password", AUTH_PREFIX);
					seUserName.addTextNode(usrKey);
					seUserPwd.addAttribute(new QName("Type"), PASSWORD_TYPE);
					seUserPwd.addTextNode(usrPwd);
				}
			} catch (final Exception e) {
				logger.error("ERROR Handler handleMessage: " + ExceptionUtils.getStackTrace(e));
				return false;
			}
		}
		return true;
	}

	@Override
	public void close(MessageContext arg0) {
		// Nada que hacer
	}

	@Override
	public boolean handleFault(SOAPMessageContext arg0) {
		// Nada que hacer
		return false;
	}

	@Override
	public Set<QName> getHeaders() {
		return new HashSet<QName>();
	}

}
