package org.jboss.qe.camel.components.ejb;

import java.io.IOException;

import javax.inject.Inject;

import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.mock.MockEndpoint;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.qe.camel.components.ejb.subA.MultipleMethodEjb;
import org.jboss.qe.camel.components.ejb.subA.RouteCaller;
import org.jboss.qe.camel.components.ejb.subA.SingleMethodEjb;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.wildfly.extension.camel.CamelContextRegistry;

@RunWith(Arquillian.class)
public class SimpleEjbTest  {

	@Inject
	private RouteCaller routeCaller;

    @ArquillianResource
    private CamelContextRegistry contextRegistry;

    private CamelContext camelctx;
    private MockEndpoint resultEp;
	private MockEndpoint errorEp;
	
	@Deployment
	public static JavaArchive createDeployment() throws IOException {
        final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "simple-ejb.jar");
        archive.addAsManifestResource("spring/simple-ejb-camel-context.xml");
        archive.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
        archive.addPackage(SingleMethodEjb.class.getPackage());
        return archive;
	}

	@Before
	public void before() {
		camelctx = contextRegistry.getCamelContext("simple-ejb-test");
		resultEp = camelctx.getEndpoint("mock:result", MockEndpoint.class);
		errorEp = camelctx.getEndpoint("mock:error", MockEndpoint.class);
	}

	@After
	public void after() {
		resultEp.reset();
		errorEp.reset();
	}

	@Test
	public void singleMethodShouldBeResolved() throws Exception {
		final String payload = "Message";
		resultEp.expectedBodiesReceived(payload + ":" + SingleMethodEjb.class.getName() + "#singleParam");

		ProducerTemplate producerTemplate = camelctx.createProducerTemplate();
		producerTemplate.sendBody("direct:singleMethodShouldBeResolved", payload);

		resultEp.assertIsSatisfied();
	}

	@Test
	public void multiMethodCannotBeResolved() throws Exception {
		resultEp.expectedMessageCount(0);
		errorEp.expectedBodiesReceived("catched:AmbiguousMethodCallException");

		ProducerTemplate producerTemplate = camelctx.createProducerTemplate();
		producerTemplate.sendBody("direct:multiMethodCannotBeResolved", "body");

		resultEp.assertIsSatisfied();
		errorEp.assertIsSatisfied();
	}

	@Test
	public void selectedMethodShouldBeInvoked() throws Exception {
		final String payload = "Message";
		resultEp.expectedBodiesReceived(payload + ":" + MultipleMethodEjb.class.getName() + "#singleParam");

		ProducerTemplate producerTemplate = camelctx.createProducerTemplate();
		producerTemplate.sendBody("direct:selectedMethodShouldBeInvoked", payload);

		resultEp.assertIsSatisfied();
	}

	@Test
	public void multipleParameterShouldBePassed() throws Exception {
		final String a = "ArgA";
		final String b = "ArgB";
		resultEp.expectedBodiesReceived("[" + a + ";" + b + "]:" + MultipleMethodEjb.class.getName() + "#multiParam");

		ProducerTemplate producerTemplate = camelctx.createProducerTemplate();
		producerTemplate.sendBody("direct:multipleParameterShouldBePassed", new String[] {a, b});

		resultEp.assertIsSatisfied();
	}

	@Test
	public void routeShouldBeInvokedFromEjb() throws Exception {
		final String payload = "Message";
		resultEp.expectedBodiesReceived(payload);

		routeCaller.start(payload);

		resultEp.assertIsSatisfied();
	}
}
