package eu.dnetlib.soap.cxf;

import java.net.URI;
import java.net.URISyntaxException;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.endpoint.Endpoint;
import org.springframework.beans.factory.annotation.Required;

/**
 * CxfEndpointReferenceBuilder is not able to create correct endpoint addresses outside a http request context. This means that service
 * initialization code cannot obtain the service address and thus cannot register himself.
 * 
 * This subclass allows putting a local address (ip/dns + port) to be used when the runtime servlet context is not available.
 * 
 * TODO: automated tomcat port detection, trough org.apache.catalina.ServerFactory.getServer().getServices() TODO: automated jetty port
 * detection
 * 
 * 
 * @author marko
 * 
 */
public class StandaloneCxfEndpointReferenceBuilder extends CxfEndpointReferenceBuilder {

	private static final Log log = LogFactory.getLog(StandaloneCxfEndpointReferenceBuilder.class); // NOPMD by marko on 11/24/08 5:02 PM

	/**
	 * base url where all services are exported.
	 */
	private String baseAddress;

	private String absoluteBase;

	private boolean forceLocalAddress = false;

	public String getBaseAddress() {
		return baseAddress;
	}

	public void setBaseAddress(final String baseAddress) {
		this.baseAddress = baseAddress;
	}

	@PostConstruct
	public void init() throws URISyntaxException {
		URI base = new URI(baseAddress);
		log.info("base address: " + baseAddress);

		this.absoluteBase = (new URI(base.getScheme(), base.getUserInfo(), base.getHost(), base.getPort(), null, null, null)).toString().trim();
		log.info("absolute base address: " + absoluteBase);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.soap.cxf.CxfEndpointReferenceBuilder#getAddress(org.apache.cxf.endpoint.Endpoint)
	 */
	@Override
	public String getAddress(final Endpoint endpoint) {
		final String address = super.getAddress(endpoint);

		if (forceLocalAddress) {
			try {
				URI uri = new URI(address);
				if (!address.startsWith("http://")) {
					String res = baseAddress + uri.getPath();
					if (log.isDebugEnabled()) {
						log.debug("fixing address to: " + res);
					}
					return res;
				}
				String res = absoluteBase + uri.getPath();
				if (log.isDebugEnabled()) {
					log.debug("forcing address to: " + res);
				}
				return res;
			} catch (URISyntaxException e) {
				throw new IllegalArgumentException(e);
			}
		}

		if (!address.startsWith("http://") && (baseAddress != null)) { return baseAddress + address; }
		return address;
	}

	public boolean isForceLocalAddress() {
		return forceLocalAddress;
	}

	@Required
	public void setForceLocalAddress(final boolean forceLocalAddress) {
		this.forceLocalAddress = forceLocalAddress;
	}
}
