/*
 * Copyright (c) eHealth
 */
package be.fgov.ehealth.technicalconnector.bootstrap.bcp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import be.fgov.ehealth.technicalconnector.tests.server.HttpServerStub;
import be.fgov.ehealth.technicalconnector.tests.utils.LoggingUtils;
import org.apache.commons.lang.StringUtils;
import org.junit.*;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.utils.ConnectorIOUtils;
import be.ehealth.technicalconnector.ws.ServiceFactory;
import be.ehealth.technicalconnector.ws.domain.GenericRequest;
import be.fgov.ehealth.technicalconnector.tests.junit.rule.EndpointUpdateRule;
import be.fgov.ehealth.technicalconnector.tests.junit.rule.HttpServerStubRule;

import static org.hamcrest.core.AnyOf.anyOf;
import static org.hamcrest.core.StringContains.containsString;

@RunWith(Parameterized.class)
public class GenericRequestCachingTest {

    private boolean mustFail;

    @Parameterized.Parameters(name = "{0}")
    public static List<Object[]> input() {
        return Arrays.asList(new Object[][]{
                {"serviceList V1", "/samples/servicelist/local/servicelist-local", true},
                {"serviceList V2", "/samples/servicelist/local/servicelistv2-local-4444", false}});
    }

    @Rule
    public EndpointUpdateRule rule = new EndpointUpdateRule();

    public GenericRequestCachingTest(String name, String endpointLocation, boolean mustFail) {
        this.mustFail = mustFail;
        rule.setLocation(endpointLocation);
    }

    @Rule
    public ExpectedException expect = ExpectedException.none();

    private HttpServerStub server4444;

    @Before
    public void before() throws Exception {
        LoggingUtils.bootstrap();

        server4444 = new HttpServerStub(4444);
        server4444.add("/error/403", (String) null);
        server4444.add("/echo", (String) null);

    }

    @After
    public void after() throws Exception {
        server4444.shutdown();
    }

    @Test
    public void walk() throws Exception {

        server4444.add("/EtkDepot/v1", ConnectorIOUtils.getResourceAsString("/samples/etkdepot-response.xml"));

        GenericRequest req = new GenericRequest();
        req.setPayload(ConnectorIOUtils.getResourceAsString("/samples/etkdepot-request.xml"));
        req.setEndpoint("http://localhost:4444/EtkDepot/v1");
        String request = ServiceFactory.getGenericWsSender()
                                       .send(req)
                                       .asString();

        Assert.assertTrue(StringUtils.contains(request, "425ad6d2-d627-4749-add2-62599834b118"));

        server4444.shutdown();
        expectException();

        req = new GenericRequest();
        req.setPayload(ConnectorIOUtils.getResourceAsString("/samples/etkdepot-request.xml"));
        req.setEndpoint("http://localhost:4444/EtkDepot/v1");
        String request2 = ServiceFactory.getGenericWsSender()
                                        .send(req)
                                        .asString();

        Assert.assertTrue(StringUtils.contains(request2, "425ad6d2-d627-4749-add2-62599834b118"));

    }

    @Test
    public void invokeWithCache() throws Exception {
        expectException();

        GenericRequest req = new GenericRequest();
        server4444.shutdown();

        req.setPayload(ConnectorIOUtils.getResourceAsString("/samples/etkdepot-request.xml"));
        req.setEndpoint("http://localhost:4444/EtkDepot/v1");
        String request2 = ServiceFactory.getGenericWsSender()
                                        .send(req)
                                        .asString();

        Assert.assertTrue(StringUtils.contains(request2, "425ad6d2-d627-4749-add2-62599834b118"));

    }


    private void expectException() {
        if (mustFail) {
            expect.expect(TechnicalConnectorException.class);
            expect.expectMessage(anyOf(containsString("refused"),containsString("Read timed out")));
        }
    }


}
