package org.jboss.cache.loader;

import org.jboss.cache.AbstractSingleCacheTest;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.UnitTestCacheFactory;
import org.jboss.cache.config.CacheLoaderConfig;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.UnitTestConfigurationFactory;
import org.jboss.cache.loader.testloaders.DummyInMemoryCacheLoader;
import org.testng.annotations.Test;

import javax.transaction.TransactionManager;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Test(groups = "functional", testName = "loader.DataOverwriteTest")
public class DataOverwriteTest extends AbstractSingleCacheTest
{
   private static final Fqn<String> FQN = Fqn.fromElements("a", "a");
   private static final Fqn<String> FQN_PARENT = FQN.getParent();
   private CacheSPI<String, String> cache;
   private TransactionManager tm;

   protected Configuration.NodeLockingScheme nls = Configuration.NodeLockingScheme.PESSIMISTIC;

   public CacheSPI createCache() throws Exception
   {
      UnitTestCacheFactory<String, String> cf = new UnitTestCacheFactory<String, String>();
      cache = (CacheSPI<String, String>) cf.createCache("configs/local-tx.xml", false, getClass());
      cache.getConfiguration().setLockAcquisitionTimeout(4000);
      // cache.getConfiguration().setEvictionConfig(null);
      cache.getConfiguration().setLockParentForChildInsertRemove(true);
      CacheLoaderConfig cacheLoaderConfig = UnitTestConfigurationFactory.buildSingleCacheLoaderConfig(false, "", DummyInMemoryCacheLoader.class.getName(), "", false, true, false, false, false);
      cache.getConfiguration().setCacheLoaderConfig(cacheLoaderConfig);
      cache.getConfiguration().setNodeLockingScheme(nls);

      cache.start();
      tm = cache.getTransactionManager();

      return cache;
   }

   public void testOverwriteGetData() throws Exception
   {
      // this will put it in the cache loader
      tm.begin();
      cache.put(FQN, "test", "test1");
      cache.evict(FQN_PARENT);
      tm.commit();

      tm.begin();

      cache.put(FQN, "test", "test2");
      cache.getChildrenNames(FQN_PARENT);
      Map<String, String> test2 = cache.getData(FQN);
      assert test2.equals(Collections.singletonMap("test", "test2")) : test2;

      tm.commit();
   }

   public void testOverwriteGet() throws Exception
   {
      // this will put it in the cache loader
      tm.begin();
      cache.put(FQN, "test", "test1");
      cache.evict(FQN_PARENT);
      tm.commit();

      tm.begin();

      cache.put(FQN, "test", "test2");
      cache.getChildrenNames(FQN_PARENT);
      String test2 = cache.get(FQN, "test");
      assert test2.equals("test2") : test2;

      tm.commit();
   }

      public void testOverwriteGetData2() throws Exception
   {
      // this will put it in the cache loader
      tm.begin();
      cache.put(FQN, "test", "test1");
      cache.put(FQN, "old", "old");
      cache.evict(FQN_PARENT);
      tm.commit();

      tm.begin();

      cache.put(FQN, "test", "test2");
      cache.getChildrenNames(FQN_PARENT);
      Map<String, String> test2 = cache.getData(FQN);
      Map<String, String> m = new HashMap<String, String>();
      m.put("test", "test2");
      m.put("old", "old");
      assert test2.equals(m) : test2;

      tm.commit();
   }

   public void testOverwriteGet2() throws Exception
   {
      // this will put it in the cache loader
      tm.begin();
      cache.put(FQN, "test", "test1");
      cache.put(FQN, "old", "old");
      cache.evict(FQN_PARENT);
      tm.commit();

      tm.begin();

      cache.put(FQN, "test", "test2");
      cache.getChildrenNames(FQN_PARENT);
      String test2 = cache.get(FQN, "test");
      assert test2.equals("test2") : test2;

      String old = cache.get(FQN, "old");
      assert old.equals("old") : old;

      tm.commit();
   }
}