/*
 * Copyright (c) eHealth
 */
package be.fgov.ehealth.technicalconnector.tests.junit.rule;

import be.fgov.ehealth.technicalconnector.tests.server.HttpServerStub;
import be.fgov.ehealth.technicalconnector.tests.utils.LoggingUtils;
import be.fgov.ehealth.technicalconnector.tests.utils.PortUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang3.StringUtils;
import org.junit.rules.ExternalResource;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * @author EHP
 */
public class HttpServerStubRule extends ExternalResource {

    private static final String SOAP_CONNECTION_FACTORY = "javax.xml.soap.SOAPConnectionFactory";

    private int port;

    private HttpServerStub server;

    private String oldConnectionFactory;

    public HttpServerStubRule() {
        this(PortUtils.getFreePort());
    }

    public HttpServerStubRule(int portNumber) {
        this.port = portNumber;
    }

    @Override
    protected void before() throws Throwable {
        LoggingUtils.bootstrap();
        Validate.isTrue(PortUtils.freePort(port), "Port " + port + " already in use!");
        server = new HttpServerStub(port);
        oldConnectionFactory = System.getProperty(SOAP_CONNECTION_FACTORY);
        System.setProperty(SOAP_CONNECTION_FACTORY, "com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnectionFactory");
    }

    @Override
    protected void after() {
        shutdown();
    }

    public void shutdown() {
        server.closeAllConnections();
        if (oldConnectionFactory != null) {
            System.setProperty(SOAP_CONNECTION_FACTORY, oldConnectionFactory);
        }
    }

    public String getEchoUrl() {
        return getContentUrl("/echo");
    }

    public String getErrorUrl(int errorCode) {
        return getContentUrl("/error/" + errorCode);
    }

    public String getTimeOutUrl(int period) {
        return getContentUrl("/timeout/" + period);
    }

    public String getContentUrl(String path, String[]... params) {
        StringBuffer url = new StringBuffer();
        url.append("http://localhost:").append(port);
        if (!StringUtils.startsWith(path, "/")) {
            url.append("/");
        }
        url.append(path);
        if (ArrayUtils.isNotEmpty(params)) {
            url.append("?");
            boolean notFirst = false;
            for (String[] param : params) {
                try {
                    if (notFirst) {
                        url.append("&");
                    }
                    url.append(param[0]).append("=").append(URLEncoder.encode(param[1], "UTF-8"));
                    notFirst = true;
                } catch (UnsupportedEncodingException e) {
                    throw new IllegalArgumentException(e);
                }
            }
        }
        return url.toString();
    }

    public String add(String path, String content, String[]... params) {
        server.add(path, content);
        return getContentUrl(path, params);
    }

    public String add(String path, HttpServerStub.HttpAsserter asserter, String[]... params) {
        if (!path.startsWith("/assert/")) {
            path = "/assert/" + path;
        }
        server.add(path, asserter);
        return getContentUrl(path, params);
    }
}