/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
using System;
using System.Threading;

namespace Apache.Geode.Client.UnitTests
{
  using NUnit.Framework;
  using Apache.Geode.DUnitFramework;
  using Apache.Geode.Client.Tests;

  using Apache.Geode.Client;

  using GIRegion = Apache.Geode.Client.IRegion<int, object>;
  using System.Collections.Generic;

  public class CallbackListener : CacheListenerAdapter<int, object>
  {
    int m_creates;
    int m_updates;
    int m_invalidates;
    int m_destroys;
    int m_regionInvalidate;
    int m_regionDestroy;
    int m_regionClear; 
    object m_callbackArg;

    #region Getters

    public int Creates
    {
      get { return m_creates; }
    }

    public int Updates
    {
      get { return m_updates; }
    }

    public int Invalidates
    {
      get { return m_invalidates; }
    }

    public int Destroys
    {
      get { return m_destroys; }
    }

    public int RegionInvalidates
    {
      get { return m_regionInvalidate; }
    }

    public int RegionDestroys
    {
      get { return m_regionDestroy; }
    }
    public int RegionClear
 	{ 
 	  get { return m_regionClear; }
 	}
    public object CallbackArg
    {
      get { return m_callbackArg; }
    }
    #endregion

    public void SetCallbackArg(object callbackArg)
    {
      m_callbackArg = callbackArg;
    }

    private void check(object eventCallback, ref int updateCount)
    {
      Log.Fine("check..");
      if (eventCallback != null)
      {
        string callbackArg = eventCallback as string;

        if (callbackArg != null)
        {
          string cs = m_callbackArg as string;
          if (cs != null)
          {
            if (callbackArg == cs)
            {
              Log.Fine("value matched");
              updateCount++;
            }
            else
              Log.Fine("value matched NOT");
          }
        }
        else
        {
          Log.Fine("Callbackarg is not cacheable string");
          Portfolio pfCallback = eventCallback as Portfolio;
          if (pfCallback != null)
          {
            Portfolio pf = m_callbackArg as Portfolio;
            if (pf != null)
            {
              if (pf.Pkid == pfCallback.Pkid && pfCallback.ArrayNull == null
                    && pfCallback.ArrayZeroSize != null && pfCallback.ArrayZeroSize.Length == 0)
              {
                Log.Fine("value matched");
                updateCount++;
              }
            }
          }
        }
      }
    }

    private void checkCallbackArg(EntryEvent<int, object> entryEvent, ref int updateCount)
    {
      check(entryEvent.CallbackArgument, ref updateCount);
    }

    private void checkCallbackArg(RegionEvent<int, object> regionEvent, ref int updateCount)
    {
      check(regionEvent.CallbackArgument, ref updateCount);
    }

    #region CacheListener Members

    public override void AfterCreate(EntryEvent<int, object> ev)
    {
      checkCallbackArg(ev, ref m_creates);
    }

    public override void AfterUpdate(EntryEvent<int, object> ev)
    {
      checkCallbackArg(ev, ref m_updates);
    }

    public override void AfterInvalidate(EntryEvent<int, object> ev)
    {
      checkCallbackArg(ev, ref m_invalidates);
    }

    public override void AfterDestroy(EntryEvent<int, object> ev)
    {
      checkCallbackArg(ev, ref m_destroys);
    }

    public override void AfterRegionInvalidate(RegionEvent<int, object> rev)
    {
      checkCallbackArg(rev, ref m_regionInvalidate);
    }

    public override void AfterRegionDestroy(RegionEvent<int, object> rev)
    {
      checkCallbackArg(rev, ref m_regionDestroy);
    }
    public override void AfterRegionClear(RegionEvent<int, object> rev)
    {
        checkCallbackArg(rev, ref m_regionClear);
    }

    #endregion
  }

  [TestFixture]
  [Category("generics")]
  public class ThinClientCallbackArg : ThinClientRegionSteps
  {
    private TallyWriter<int, object> m_writer;
    private TallyListener<int, object> m_listener;
    private CallbackListener m_callbackListener;
    RegionOperation o_region;
    private UnitProcess m_client1, m_client2;
    int key0 = 12;
    object m_callbackarg = "Gemstone's Callback";
    
    protected override ClientBase[] GetClients()
    {
      m_client1 = new UnitProcess();
      m_client2 = new UnitProcess();
      return new ClientBase[] { m_client1, m_client2 };
    }

    public void CreateRegion(string locators,
      bool caching, bool listener, bool writer)
    {
      if (listener)
      {
        m_listener = new TallyListener<int, object>();

      }
      else
      {
        m_listener = null;
      }
      GIRegion region = null;
      region = CacheHelper.CreateTCRegion_Pool<int, object>(RegionName, true, caching,
        m_listener, locators, "__TESTPOOL1_", true);
      if (listener)
        m_listener.SetCallBackArg(key0);

      if (writer)
      {
        m_writer = new TallyWriter<int, object>();

      }
      else
      {
        m_writer = null;
      }
      if (writer)
      {
        AttributesMutator<int, object> at = region.AttributesMutator;
        at.SetCacheWriter(m_writer);
        m_writer.SetCallBackArg(key0);
      }
    }

    public void CreateRegion2(string locators,
      bool caching, bool listener, bool writer)
    {
      CallbackListener callbackLis = null;
      if (listener)
      {
        m_callbackListener = new CallbackListener();
        m_callbackListener.SetCallbackArg(m_callbackarg);
        callbackLis = m_callbackListener;
      }
      else
      {
        m_listener = null;
      }
      GIRegion region = null;
      region = CacheHelper.CreateTCRegion_Pool<int, object>(RegionName, true, caching,
        callbackLis, locators, "__TESTPOOL1_", true);
      CacheHelper.DCache.TypeRegistry.RegisterType(Portfolio.CreateDeserializable, 8);
      CacheHelper.DCache.TypeRegistry.RegisterType(Position.CreateDeserializable, 7);
    }

    public void ValidateLocalListenerWriterData()
    {
      Thread.Sleep(2000);
      Assert.AreEqual(true, m_writer.IsWriterInvoked, "Writer should be invoked");
      Assert.AreEqual(true, m_listener.IsListenerInvoked, "Listener should be invoked");
      Assert.AreEqual(true, m_writer.IsCallBackArgCalled, "Writer CallbackArg should be invoked");
      Assert.AreEqual(true, m_listener.IsCallBackArgCalled, "Listener CallbackArg should be invoked");
      m_listener.ShowTallies();
      m_writer.ShowTallies();
    }

    public void ValidateEvents()
    {
      Assert.AreEqual(15, m_writer.Creates, "Should be 10 creates");
      Assert.AreEqual(15, m_listener.Creates, "Should be 10 creates");
      Assert.AreEqual(15, m_writer.Updates, "Should be 5 updates");
      Assert.AreEqual(15, m_listener.Updates, "Should be 5 updates");
      Assert.AreEqual(0, m_writer.Invalidates, "Should be 0 invalidates");
      Assert.AreEqual(5, m_listener.Invalidates, "Should be 5 invalidates");
      Assert.AreEqual(10, m_writer.Destroys, "Should be 10 destroys");  // 5 destroys + 5 removes
      Assert.AreEqual(10, m_listener.Destroys, "Should be 10 destroys"); // 5 destroys + 5 removes
    }

    public void CallOp()
    {
      o_region = new RegionOperation(RegionName);
      o_region.PutOp(5, key0);
      Thread.Sleep(1000); // let the events reach at other end.
      o_region.PutOp(5, key0);
      Thread.Sleep(1000);
      o_region.InvalidateOp(5, key0);
      Thread.Sleep(1000);
      o_region.DestroyOp(5, key0);
      Thread.Sleep(1000); // let the events reach at other end.
      o_region.PutOp(5, key0);
      Thread.Sleep(1000);
      o_region.RemoveOp(5, key0);
      Thread.Sleep(1000);
    }

    void RegisterPdxType8()
    {
      CacheHelper.DCache.TypeRegistry.RegisterPdxType(PdxTests.PdxTypes8.CreateDeserializable);
    }

    void runCallbackArgTest()
    {
      CacheHelper.SetupJavaServers(true, "cacheserver_notify_subscription.xml");
      CacheHelper.StartJavaLocator(1, "GFELOC");
      Util.Log("Locator started");
      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
      Util.Log("Cacheserver 1 started.");

      Util.Log("Creating region in client1, no-ack, cache-enabled, with listener and writer");
      m_client1.Call(CreateRegion, CacheHelper.Locators,
        true, true, true);
      m_client1.Call(RegisterAllKeys, new string[] { RegionName });

      Util.Log("Creating region in client2 , no-ack, cache-enabled, with listener and writer");
      m_client2.Call(CreateRegion, CacheHelper.Locators,
        true, true, true);
      m_client2.Call(RegisterAllKeys, new string[] { RegionName });

      m_client2.Call(RegisterPdxType8);

      m_client1.Call(CallOp);
      

      m_client1.Call(ValidateLocalListenerWriterData);
      m_client1.Call(ValidateEvents);

      m_client1.Call(CacheHelper.Close);
      m_client2.Call(CacheHelper.Close);

      CacheHelper.StopJavaServer(1);
      Util.Log("Cacheserver 1 stopped.");

      CacheHelper.StopJavaLocator(1);
      Util.Log("Locator stopped");

      CacheHelper.ClearLocators();
      CacheHelper.ClearEndpoints();
    }

    private bool m_isSet = false;
    public void SetCallbackArg()
    {
      if (!m_isSet)
      {
        m_isSet = true;
        m_callbackarg = new Portfolio(1, 1);
      }
    }

    public void TestCreatesAndUpdates()
    {
      o_region = new RegionOperation(RegionName);
      o_region.Region.Add("Key-1", "Val-1", m_callbackarg);
      o_region.Region.Put("Key-1", "NewVal-1", m_callbackarg);
      Thread.Sleep(10000);
    }

    public void TestInvalidates()
    {
      o_region = new RegionOperation(RegionName);
      o_region.Region.GetLocalView().Add(1234, 1234, m_callbackarg);
      o_region.Region.GetLocalView().Add(12345, 12345, m_callbackarg);
      o_region.Region.GetLocalView().Add(12346, 12346, m_callbackarg);
      o_region.Region.GetLocalView().Put(1234, "Val-1", m_callbackarg);
      o_region.Region.GetLocalView().Invalidate(1234, m_callbackarg);
      Assert.AreEqual(o_region.Region.GetLocalView().Remove(12345, 12345, m_callbackarg), true, "Result of remove should be true, as this value exists locally.");
      Assert.AreEqual(o_region.Region.GetLocalView().ContainsKey(12345), false, "containsKey should be false");
      Assert.AreEqual(o_region.Region.GetLocalView().Remove(12346, m_callbackarg), true, "Result of remove should be true, as this value exists locally.");
      Assert.AreEqual(o_region.Region.GetLocalView().ContainsKey(12346), false, "containsKey should be false"); 
      o_region.Region.Invalidate("Key-1", m_callbackarg);
      o_region.Region.InvalidateRegion(m_callbackarg);
    }

    public void TestDestroy()
    {
      o_region = new RegionOperation(RegionName);
      o_region.Region.Remove("Key-1", m_callbackarg);
      //o_region.Region.DestroyRegion(m_callbackarg);
    }

    public void TestRemove()
    {
      o_region = new RegionOperation(RegionName);
      o_region.Region.Remove("Key-1", "NewVal-1", m_callbackarg);
      o_region.Region.DestroyRegion(m_callbackarg);
    }

    public void TestlocalClear()
    {
        o_region = new RegionOperation(RegionName);
        o_region.Region.GetLocalView().Clear(m_callbackarg); 
    }
    public void TestValidate()
    {
      Thread.Sleep(10000);
      Assert.AreEqual(5, m_callbackListener.Creates, "Should be 5 creates");
      Assert.AreEqual(3, m_callbackListener.Updates, "Should be 3 update");
      Assert.AreEqual(2, m_callbackListener.Invalidates, "Should be 2 invalidate");
      Assert.AreEqual(4, m_callbackListener.Destroys, "Should be 4 destroy");
      Assert.AreEqual(1, m_callbackListener.RegionInvalidates, "Should be 1 region invalidates");
      Assert.AreEqual(1, m_callbackListener.RegionDestroys, "Should be 1 regiondestroy");
      Assert.AreEqual(1, m_callbackListener.RegionClear, "Should be 1 RegionClear");
    }

    void runCallbackArgTest2(int callbackArgChange)
    {
      if (callbackArgChange == 1)
      {
        //change now custom type
        m_callbackarg = new Portfolio(1, 1);
        m_client1.Call(SetCallbackArg);
        m_client2.Call(SetCallbackArg);
      }

      m_callbackListener = new CallbackListener();
      m_callbackListener.SetCallbackArg(m_callbackarg);
      CacheHelper.SetupJavaServers(true, "cacheserver_notify_subscription5N.xml");
      CacheHelper.StartJavaLocator(1, "GFELOC");
      Util.Log("Locator started");
      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
      Util.Log("Cacheserver 1 started.");

      Util.Log("Creating region in client1, no-ack, cache-enabled, with listener and writer");
      m_client1.Call(CreateRegion2, CacheHelper.Locators,
        true, true, false);
      m_client1.Call(RegisterAllKeys, new string[] { RegionName });

      Util.Log("Creating region in client2 , no-ack, cache-enabled, with listener and writer");
      m_client2.Call(CreateRegion2, CacheHelper.Locators,
        true, false, false);

      m_client2.Call(TestCreatesAndUpdates);
      m_client1.Call(TestInvalidates);
      m_client2.Call(TestDestroy);
      m_client2.Call(TestCreatesAndUpdates);
      m_client1.Call(TestlocalClear); 
      m_client2.Call(TestRemove);
      m_client1.Call(TestValidate);

      m_client1.Call(CacheHelper.Close);
      m_client2.Call(CacheHelper.Close);

      CacheHelper.StopJavaServer(1);
      Util.Log("Cacheserver 1 stopped.");

      CacheHelper.StopJavaLocator(1);
      Util.Log("Locator stopped");

      CacheHelper.ClearLocators();
      CacheHelper.ClearEndpoints();
    }

    private bool isRegistered = false;
    public void registerDefaultCacheableType()
    {
      if (!isRegistered)
      {
        CacheHelper.DCache.TypeRegistry.RegisterType(DefaultType.CreateDeserializable, 4);
        isRegistered = true;
      }
    }


    public void CallOp2()
    {
      o_region = new RegionOperation(RegionName);
      DefaultType dc = new DefaultType(true);
      o_region.Region.Put("key-1", dc, null);
      Thread.Sleep(1000); // let the events reach at other end.
    }

    public void ValidateData()
    {
      o_region = new RegionOperation(RegionName);
      DefaultType dc = (DefaultType)o_region.Region.Get("key-1", null);

      Assert.AreEqual(dc.CBool, true, "bool is not equal");
      Assert.AreEqual(dc.CInt, 1000, "int is not equal");

      int[] cia = dc.CIntArray;
      Assert.IsNotNull(cia, "Int array is null");
      Assert.AreEqual(3, cia.Length, "Int array are not three");

      string[] csa = dc.CStringArray;
      Assert.IsNotNull(csa, "String array is null");
      Assert.AreEqual(2, csa.Length, "String array length is not two");

      Assert.AreEqual(dc.CFileName, "geode.txt", "Cacheable filename is not equal");

      /*
      Assert.IsNotNull(dc.CHashSet, "hashset is null");
      Assert.AreEqual(2, dc.CHashSet.Count, "hashset size is not two");
       * */

      Assert.IsNotNull(dc.CHashMap, "hashmap is null");
      Assert.AreEqual(1, dc.CHashMap.Count, "hashmap size is not one");

      //Assert.IsNotNull(dc.CDate, "Date is null");

      Assert.IsNotNull(dc.CVector);
      Assert.AreEqual(2, dc.CVector.Count, "Vector size is not two");

      //Assert.IsNotNull(dc.CObject);
      //Assert.AreEqual("key", ((CustomSerializableObject)dc.CObject).key, "Object key is not same");
      //Assert.AreEqual("value", ((CustomSerializableObject)dc.CObject).value, "Object value is not same");
    }

    void runCallbackArgTest3()
    {

      CacheHelper.SetupJavaServers(true, "cacheserver_notify_subscription6.xml");
      CacheHelper.StartJavaLocator(1, "GFELOC");
      Util.Log("Locator started");
      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
      Util.Log("Cacheserver 1 started.");

      Util.Log("Creating region in client1, no-ack, cache-enabled, with listener and writer");
      m_client1.Call(CreateRegion, CacheHelper.Locators,
        true, false, false);
      // m_client1.Call(RegisterAllKeys, new string[] { RegionName });

      Util.Log("Creating region in client2 , no-ack, cache-enabled, with listener and writer");
      m_client2.Call(CreateRegion, CacheHelper.Locators,
        true, false, false);

      m_client1.Call(registerDefaultCacheableType);
      m_client2.Call(registerDefaultCacheableType);

      m_client2.Call(RegisterAllKeys, new string[] { RegionName });

      m_client1.Call(CallOp2);

      m_client2.Call(ValidateData);

      m_client1.Call(CacheHelper.Close);
      m_client2.Call(CacheHelper.Close);

      CacheHelper.StopJavaServer(1);
      Util.Log("Cacheserver 1 stopped.");

      CacheHelper.StopJavaLocator(1);
      Util.Log("Locator stopped");

      CacheHelper.ClearLocators();
      CacheHelper.ClearEndpoints();
    }

    public void TestRemoveAll()
    {
      o_region = new RegionOperation(RegionName);
      ICollection<object> keys = new LinkedList<object>(); 
      for(int i =0; i< 10; i++)
      {
        o_region.Region["Key-"+i] = "Value-"+i;
        keys.Add("Key-" + i);
      }
      o_region.Region.RemoveAll(keys, m_callbackarg);
    }

    public void TestPutAll()
    {
      o_region = new RegionOperation(RegionName);
      Dictionary<Object, Object> entryMap = new Dictionary<Object, Object>();
      for (Int32 item = 0; item < 10; item++)
      {
        int K = item;
        string value = item.ToString();
        entryMap.Add(K, value);
      }
      o_region.Region.PutAll(entryMap, TimeSpan.FromSeconds(15), m_callbackarg);
    }

    public void TestGetAll()
    {
      o_region = new RegionOperation(RegionName);
      List<Object> keys = new List<Object>();
      for (int item = 0; item < 10; item++)
      {
        Object K = item;
        keys.Add(K);
      }
      Dictionary<Object, Object> values = new Dictionary<Object, Object>();
      o_region.Region.GetAll(keys.ToArray(), values, null, true, m_callbackarg);

      Dictionary<Object, Object>.Enumerator enumerator = values.GetEnumerator();
      while (enumerator.MoveNext())
      {
        Util.Log("Values after getAll with CallBack Key = {0} Value = {1} ", enumerator.Current.Key.ToString(), enumerator.Current.Value.ToString());
      }
    }

    public void TestValidateRemoveAllCallback()
    {
      Thread.Sleep(10000);
      Assert.AreEqual(10, m_callbackListener.Destroys, "Should be 10 destroy");
    }

    public void TestValidatePutAllCallback()
    {
      Thread.Sleep(10000);
      Assert.AreEqual(10, m_callbackListener.Creates, "Should be 10 creates");      
      Assert.AreEqual("Gemstone's Callback", m_callbackListener.CallbackArg, "CallBackArg for putAll should be same");
    }

    void runPutAllCallbackArgTest()
    {
      m_callbackListener = new CallbackListener();
      m_callbackListener.SetCallbackArg(m_callbackarg);
      
      CacheHelper.SetupJavaServers(true, "cacheserver_notify_subscription5N.xml");
      CacheHelper.StartJavaLocator(1, "GFELOC");
      Util.Log("Locator started");
      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
      Util.Log("Cacheserver 1 started.");

      Util.Log("Creating region in client1, no-ack, cache-enabled, with listener and writer");
      m_client1.Call(CreateRegion2, CacheHelper.Locators,
        true, true, false);
      m_client1.Call(RegisterAllKeys, new string[] { RegionName });
      Util.Log("RegisterAllKeys completed..");

      Util.Log("Creating region in client2 , no-ack, cache-enabled, with listener and writer");
      m_client2.Call(CreateRegion2, CacheHelper.Locators,
        true, false, false);
      Util.Log("CreateRegion2 completed..");

      m_client2.Call(TestPutAll);
      Util.Log("TestPutAll completed..");
      m_client1.Call(TestValidatePutAllCallback);
      Util.Log("TestValidatePutAllCallback completed..");
      m_client2.Call(TestGetAll);
      Util.Log("TestGetAll completed..");

      m_client1.Call(CacheHelper.Close);
      m_client2.Call(CacheHelper.Close);

      CacheHelper.StopJavaServer(1);
      Util.Log("Cacheserver 1 stopped.");

      CacheHelper.StopJavaLocator(1);
      Util.Log("Locator stopped");

      CacheHelper.ClearLocators();
      CacheHelper.ClearEndpoints();
    }

    void runRemoveAllCallbackArgTest()
    {

      m_callbackListener = new CallbackListener();
      m_callbackListener.SetCallbackArg(m_callbackarg);
      CacheHelper.SetupJavaServers(true, "cacheserver_notify_subscription5N.xml");
      CacheHelper.StartJavaLocator(1, "GFELOC");
      Util.Log("Locator started");
      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
      Util.Log("Cacheserver 1 started.");

      Util.Log("Creating region in client1, no-ack, cache-enabled, with listener and writer");
      m_client1.Call(CreateRegion2, CacheHelper.Locators,
        true, true, false);
      m_client1.Call(RegisterAllKeys, new string[] { RegionName });
      Util.Log("RegisterAllKeys completed..");

      Util.Log("Creating region in client2 , no-ack, cache-enabled, with listener and writer");
      m_client2.Call(CreateRegion2,CacheHelper.Locators,
        true, false, false);
      Util.Log("CreateRegion2 completed..");

      m_client2.Call(TestRemoveAll);
      Util.Log("TestRemoveAll completed..");
      m_client1.Call(TestValidateRemoveAllCallback);
      Util.Log("TestValidateRemoveAllCallback completed..");

      m_client1.Call(CacheHelper.Close);
      m_client2.Call(CacheHelper.Close);

      CacheHelper.StopJavaServer(1);
      Util.Log("Cacheserver 1 stopped.");

      CacheHelper.StopJavaLocator(1);
      Util.Log("Locator stopped");

      CacheHelper.ClearLocators();
      CacheHelper.ClearEndpoints();
    }

    [TearDown]
    public override void EndTest()
    {
      base.EndTest();
    }

    [Test]
    public void ThinClientCallbackArgTest()
    {
      runCallbackArgTest();
    }

    [Test]
    public void ThinClientCallbackArgTest2()
    {
      for (int i = 0; i < 2; i++)
      {
        runCallbackArgTest2(i);
      }
    }

    [Test]
    public void ThinClientCallbackArgTest3()
    {
      runCallbackArgTest3();
    }

    [Test]
    public void RemoveAllCallbackArgTest()
    {
      runRemoveAllCallbackArgTest();
    }

    [Test]
    public void PutAllCallbackArgTest()
    {
      runPutAllCallbackArgTest();
    }
  }
}
