package org.jboss.cache.pojo;

import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.aop.proxy.ClassProxy;
import org.jboss.cache.Fqn;
import org.jboss.cache.pojo.impl.InternalConstant;
import org.jboss.cache.pojo.test.Person;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

/**
 * Additional basic tests
 *
 * @author Ben Wang
 */

@Test(groups = {"functional"})
public class NewLocalTest
{
   Log log_ = LogFactory.getLog(NewLocalTest.class);
   PojoCache cache_;


   @BeforeMethod(alwaysRun = true)
   protected void setUp() throws Exception
   {
      log_.info("setUp() ....");
      String configFile = "META-INF/local-service.xml";
      boolean toStart = false;
      cache_ = PojoCacheFactory.createCache(configFile, toStart);
      cache_.start();
   }

   @AfterMethod(alwaysRun = true)
   protected void tearDown() throws Exception
   {
      cache_.stop();
   }

//   public void testDummy() {}

   @Test(enabled = false)
   public void XtestBadFqn() throws Exception
   {
      log_.info("testBadFqn() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache_.attach("/a", test);
      Person result = (Person) cache_.detach("/a");
      assertEquals(" ", test, result);
      result.setAge(20);

      try
      {
         cache_.attach(InternalConstant.JBOSS_INTERNAL_STRING, test);
         fail("putObject under JBoss_Internal should fail");
      }
      catch (IllegalArgumentException iex)
      {
         // ok
      }

      try
      {
         cache_.detach(InternalConstant.JBOSS_INTERNAL_STRING);
         fail("putObject under JBoss_Internal should fail");
      }
      catch (IllegalArgumentException iex)
      {
         // ok
      }
   }

   public void testPutRemove() throws Exception
   {
      log_.info("testPutRemove() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache_.attach("/a", test);
      Person result = (Person) cache_.find("/a");
      assertEquals(" ", test, result);
      result.setAge(20);
      cache_.detach("/a");
      assertNull("Object should be null ", cache_.find("/a"));
      assertEquals("Age should be updated as ", 20, test.getAge());
   }

   public void testPutRemoveNodeExistence() throws Exception
   {
      log_.info("testPutRemove() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache_.attach("person", test);
      Person result = (Person) cache_.find("person");
      assertEquals(" ", test, result);
      result.setAge(20);
      cache_.detach("person");
      assertNull("Object should be null ", cache_.find("person"));
      assertEquals("Age should be updated as ", 20, test.getAge());

      assertNull("DataNode should not exisit ", cache_.getCache().getRoot().getChild(Fqn.fromString("person")));
   }

   public void testRemoveProxyList() throws Exception
   {
      log_.info("testRemoveProxyList() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      ArrayList<String> list = new ArrayList<String>();
      list.add("English");
      list.add("Taiwanese");
      test.setLanguages(list);
      cache_.attach("/a", test);
      Person result = (Person) cache_.find("/a");
      assertEquals(" ", test, result);

      assertTrue("Instance of proxyclass ", result.getLanguages() instanceof ClassProxy);

      Person r1 = (Person) cache_.detach("/a");

      assertEquals("Same instance ", result, r1);
      assertFalse("Instance of proxyclass ", result.getLanguages() instanceof ClassProxy);
      assertEquals("Same Collection instance", list, result.getLanguages());
   }

   public void testRemoveProxySet() throws Exception
   {
      log_.info("testRemoveProxySet() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      HashSet<String> set = new HashSet<String>();
      set.add("Golf");
      set.add("Cooking");
      test.setSkills(set);
      cache_.attach("/a", test);
      Person result = (Person) cache_.find("/a");
      assertEquals(" ", test, result);

      assertTrue("Instance of proxyclass ", result.getSkills() instanceof ClassProxy);

      Person r1 = (Person) cache_.detach("/a");

      assertEquals("Same instance ", result, r1);
      assertFalse("Instance of proxyclass ", result.getSkills() instanceof ClassProxy);
      assertEquals("Same Collection instance", set, result.getSkills());
   }

   public void testRemoveProxyMap() throws Exception
   {
      log_.info("testRemoveProxyMap() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);

      HashMap<String, String> map = new HashMap<String, String>();
      map.put("1", "Golf");
      map.put("2", "Surfing");
      test.setHobbies(map);

      cache_.attach("/a", test);
      Person result = (Person) cache_.find("/a");
      assertEquals(" ", test, result);

      assertTrue("Instance of proxyclass ", result.getHobbies() instanceof ClassProxy);

      Person r1 = (Person) cache_.detach("/a");

      assertEquals("Same instance ", result, r1);
      assertFalse("Instance of proxyclass ", result.getHobbies() instanceof ClassProxy);
      assertEquals("Same Collection instance", map, result.getHobbies());
   }

   public void testFindObjects() throws Exception
   {
      log_.info("testFindObjects() ....");
      Map<?, ?> map = cache_.findAll("/");
      assertEquals("Objects size should be ", 0, map.size());
      Person ben = new Person();
      ben.setName("Ben");
      ben.setAge(10);
      cache_.attach("/a/b/c", ben);
      cache_.attach("/e", ben); // multiple keys, same pojo
      Person joe = new Person();
      joe.setName("Joe");
      joe.setAge(10);
      cache_.attach("/f/joe", joe);
      map = cache_.findAll("/");
      assertEquals("Objects size should be ", 3, map.size());

      map = cache_.findAll("/a");
      assertEquals("Objects size should be ", 1, map.size());
      cache_.detach("/e");
      map = cache_.findAll("/");
      assertEquals("Objects size should be ", 2, map.size());

      map = cache_.findAll((String)null); // should everything.
      assertEquals("Objects size should be ", 2, map.size());
   }
}

