package org.jboss.cache.pojo.integrated;

import static org.testng.AssertJUnit.assertEquals;

import org.jboss.cache.Fqn;
import org.jboss.cache.config.Configuration.CacheMode;
import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
import org.jboss.cache.pojo.PojoCache;
import org.jboss.cache.pojo.PojoCacheFactory;
import org.jboss.cache.pojo.test.propagation.PropagationManager;
import org.jboss.cache.pojo.test.propagation.impl.PropagationManagerImpl;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

@Test(groups = {"functional"})
public class ReplicatedPropagationManagerlTest 
{
   private PropagationManager pm_;
   private PojoCache cache1_;
   private PojoCache cache2_;

   @BeforeMethod(alwaysRun = true)
   protected void setUp() throws Exception
   {
      cache1_ = createCache("TestCluster");
      cache2_ = createCache("TestCluster");
   }

   @AfterMethod(alwaysRun = true)
   protected void tearDown() throws Exception
   {
      cache1_.getCache().removeNode(Fqn.fromString("/"));
      cache1_.stop();
      cache2_.stop();
   }

   private PojoCache createCache(String name) throws Exception
   {
      boolean toStart = false;
      PojoCache cache = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
      cache.start();
      return cache;
   }

   protected void initSimplifiedPm()
   {
      pm_ = new PropagationManagerImpl();

      pm_.setRootNode("root");
      pm_.addNode("root", "kanto");
      pm_.addNode("root.kanto", "tokyo");
      pm_.addStateItem("root.kanto.tokyo", 1000, 1040);
      pm_.addNode("root.kanto", "kanagawa");
/*
        pm_.addStateItem("root.kanto.tokyo", 1001, 1040);
        pm_.addStateItem("root.kanto.tokyo", 1002, 1040);
        pm_.addNode("root.kanto.tokyo", "shinjuku");
        pm_.addStateItem("root.kanto.tokyo.shinjuku", 1000, 1040);
        pm_.addStateItem("root.kanto.tokyo.shinjuku", 1001, 1040);
        pm_.addStateItem("root.kanto.tokyo.shinjuku", 1002, 1040);
        pm_.addNode("root.kanto.kanagawa", "kawasaki");
        pm_.addStateItem("root.kanto.kanagawa.kawasaki", 1005, 1040);
        pm_.addStateItem("root.kanto.kanagawa.kawasaki", 1006, 1040);
        pm_.addStateItem("root.kanto.kanagawa.kawasaki", 1007, 1030);
      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("Initial pm state");
      System.out.println("---------------------------------------------");
      pm_.printNodes();
*/
   }

   public void testSimplified() throws Exception
   {
      initSimplifiedPm();

      // Put pm into cache management first
      cache1_.attach("/propagation", pm_);
      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("Initial cache content");
      System.out.println("---------------------------------------------");

      PropagationManager pm1 = (PropagationManager) cache2_.find("/propagation");
      assertEquals("PropagationManager should ", pm_.toString(), pm1.toString());

      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("root.kanto.kanagawa.kawasaki:1007  1030->1031");
      System.out.println("---------------------------------------------");
      pm_.stateChange("root.kanto.kanagawa.kawasaki", 1007, 1031);
      pm_.printNodes();

      /*
      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("Final cache content");
      System.out.println(cache_.printDetails());
      System.out.println("---------------------------------------------");
      */
   }

   protected void initPm()
   {
      pm_ = new PropagationManagerImpl();

      pm_.setRootNode("root");
      pm_.addNode("root", "kanto");
      pm_.addNode("root.kanto", "tokyo");
      pm_.addStateItem("root.kanto.tokyo", 1000, 1040);
      pm_.addStateItem("root.kanto.tokyo", 1001, 1040);
      pm_.addStateItem("root.kanto.tokyo", 1002, 1040);
      pm_.addNode("root.kanto.tokyo", "shinjuku");
      pm_.addStateItem("root.kanto.tokyo.shinjuku", 1000, 1040);
      pm_.addStateItem("root.kanto.tokyo.shinjuku", 1001, 1040);
      pm_.addStateItem("root.kanto.tokyo.shinjuku", 1002, 1040);
      pm_.addNode("root.kanto", "kanagawa");
      pm_.addNode("root.kanto.kanagawa", "kawasaki");
      pm_.addStateItem("root.kanto.kanagawa.kawasaki", 1005, 1040);
      pm_.addStateItem("root.kanto.kanagawa.kawasaki", 1006, 1040);
      pm_.addStateItem("root.kanto.kanagawa.kawasaki", 1007, 1030);
   }

   public void testPropagation() throws Exception
   {
      initPm();
      // Put pm into cache management first
      cache1_.attach("/propagation", pm_);
      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("Initial cache content");
      System.out.println("---------------------------------------------");

      PropagationManager pm1 = (PropagationManager) cache2_.find("/propagation");
      assertEquals("PropagationManager should ", pm_.toString(), pm1.toString());

      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("Initial pm state");
      System.out.println("---------------------------------------------");
      pm_.printNodes();

      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("root.kanto.kanagawa.kawasaki:1007  1030->1031");
      System.out.println("---------------------------------------------");
      pm_.stateChange("root.kanto.kanagawa.kawasaki", 1007, 1031);
      pm_.printNodes();

      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("root.kanto.tokyo.shinjuku:1001  1040->1041");
      System.out.println("---------------------------------------------");
      pm_.stateChange("root.kanto.tokyo.shinjuku", 1001, 1041);
      pm_.printNodes();

      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("root.kanto.kanagawa.kawasaki:1006  1040->1041");
      System.out.println("---------------------------------------------");
      pm_.stateChange("root.kanto.kanagawa.kawasaki", 1006, 1041);
      pm_.printNodes();

      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("add new item to root.kanto.kanagawa.kawasaki:1008 default:1021");
      System.out.println("---------------------------------------------");
      pm_.addStateItem("root.kanto.kanagawa.kawasaki", 1008, 1021);
      pm_.printNodes();

      System.out.println("\n\n");
      System.out.println("---------------------------------------------");
      System.out.println("Final cache content");
      System.out.println("---------------------------------------------");
   }
}
