package org.infinispan.server.test.cs.remote;

import org.infinispan.arquillian.core.InfinispanResource;
import org.infinispan.arquillian.core.RemoteInfinispanServer;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.Configuration;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
import org.infinispan.server.test.category.CacheStore;
import org.jboss.arquillian.container.test.api.ContainerController;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
 * @author <a href="mailto:mgencur@redhat.com">Martin Gencur</a>
 */
@RunWith(Arquillian.class)
@Category(CacheStore.class)
public class RemoteCacheStoreClusteredIT {

    private final String CONTAINER_LOCAL = "standalone-rcs-local";
    private final String CONTAINER_REMOTE1 = "clustered-rcs-remote-1";
    private final String CONTAINER_REMOTE2 = "clustered-rcs-remote-2";
    private final String WRITE_THROUGH_CACHE_NAME = "writeThroughCache";

    RemoteCache<Object, Object> cache;

    @InfinispanResource(CONTAINER_LOCAL)
    RemoteInfinispanServer server1;

    @InfinispanResource(CONTAINER_REMOTE1)
    RemoteInfinispanServer server2;

    @InfinispanResource(CONTAINER_REMOTE2)
    RemoteInfinispanServer server3;

    @ArquillianResource
    ContainerController controller;

    RemoteCacheManager rcm1;

    @Test
    public void testRetryAfterClusterShutdown() throws Exception {
       try {
           controller.start(CONTAINER_REMOTE1);
           controller.start(CONTAINER_REMOTE2);
           controller.start(CONTAINER_LOCAL);

           Configuration conf = new ConfigurationBuilder()
                   .addServer()
                   .host(server1.getHotrodEndpoint().getInetAddress().getHostName())
                   .port(server1.getHotrodEndpoint().getPort())
                   .build();
           rcm1 = new RemoteCacheManager(conf);
           RemoteCache<String, String> cache = rcm1.getCache(WRITE_THROUGH_CACHE_NAME);

           cache.put("k1", "v1");
           cache.put("k2", "v2");
           assertEquals("v1", cache.get("k1"));
           assertEquals("v2", cache.get("k2"));
           controller.kill(CONTAINER_REMOTE1);
           assertEquals("v1", cache.get("k1"));
           assertEquals("v2", cache.get("k2"));
           controller.kill(CONTAINER_REMOTE2);

           try {
               assertEquals("v1", cache.get("k1"));
               assertEquals("v2", cache.get("k2"));
               fail("Should have thrown exception");
           } catch (HotRodClientException e) {
               assertTrue(e.getMessage().contains("TransportException"));
           }

           controller.start(CONTAINER_REMOTE1);

           cache.put("k1", "v1");
           assertEquals("v1", cache.get("k1"));
           cache.put("k2", "v2");
           assertEquals("v2", cache.get("k2"));
           cache.put("k3", "v3");
           assertEquals("v3", cache.get("k3"));
       } finally {
           controller.stop(CONTAINER_LOCAL);
           controller.stop(CONTAINER_REMOTE1);
           controller.stop(CONTAINER_REMOTE2);
       }
    }

}
