/*
 * 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.
 */
package org.apache.geode.internal.cache.ha;

import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.internal.cache.ha.HAConflationDUnitTest.LOCK;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import java.util.Properties;

import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.CacheListener;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.Declarable;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.RegionEvent;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache30.CacheSerializableRunnable;
import org.apache.geode.cache30.ClientServerTestCase;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.internal.AvailablePort;
import org.apache.geode.internal.cache.CacheServerImpl;
import org.apache.geode.internal.cache.tier.sockets.ConflationDUnitTestHelper;
import org.apache.geode.test.awaitility.GeodeAwaitility;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.NetworkUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.WaitCriterion;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
import org.apache.geode.test.junit.categories.ClientSubscriptionTest;

/**
 * This is Targetted conflation Dunit test. 1 Client & 1 Server. Slow down the dispatcher. From the
 * unit controller VM using separate invoke every time so that different thread context are created
 * on the server ,test the following 1) Do a create & then update on same key , the client should
 * receive 2 calabcks. 2) Do create , then update & update. The client should receive 2 callbacks ,
 * one for create & one for the last update. 3) Do create , then update, update, invalidate. The
 * client should receive 3 callbacks, one for create one for the last update and one for the
 * invalidate. 4) Do a create , update , update & destroy. The client should receive 3 callbacks (
 * craete , conflated update & destroy).
 */
@Category({ClientSubscriptionTest.class})
public class HAConflationDUnitTest extends JUnit4CacheTestCase {

  VM server1 = null;

  VM client1 = null;

  private static final String regionName = "HAConflationDUnitTest_region";

  static final String KEY1 = "KEY1";

  static final String KEY2 = "KEY2";

  static final String KEY3 = "KEY3";

  static final String VALUE1 = "VALUE1";

  static final String VALUE2 = "VALUE2";

  static final String VALUE3 = "VALUE3";

  static final String LAST_KEY = "lastkey";

  static final String LAST_VALUE = "lastvalue";

  static boolean lastKeyArrived = false;

  static Object LOCK = new Object();

  static int expectedNoEvents = 2;

  static int actualNoEvents = 0;

  public HAConflationDUnitTest() {
    super();
  }

  @Override
  public final void postSetUp() throws Exception {
    final Host host = Host.getHost(0);
    // Server1 VM
    server1 = host.getVM(0);

    // Client 1 VM
    client1 = host.getVM(2);

    int PORT1 = ((Integer) server1
        .invoke(() -> HAConflationDUnitTest.createServerCache(new Boolean(false)))).intValue();
    server1.invoke(() -> ConflationDUnitTestHelper.setIsSlowStart());
    server1.invoke(() -> HAConflationDUnitTest.makeDispatcherSlow());
    client1
        .invoke(() -> HAConflationDUnitTest.createClientCache(NetworkUtils.getServerHostName(host),
            new Integer(PORT1), new Boolean(true)));
  }

  @Override
  public final void postTearDownCacheTestCase() throws Exception {
    client1.invoke(() -> HAConflationDUnitTest.closeCacheAndDisconnect());
    // close server
    server1.invoke(() -> HAConflationDUnitTest.closeCacheAndDisconnect());
  }

  public static void closeCacheAndDisconnect() {
    if (basicGetCache() != null && !basicGetCache().isClosed()) {
      basicGetCache().close();
      basicGetCache().getDistributedSystem().disconnect();
    }
  }

  /**
   * In this test do a create & then update on same key , the client should receive 2 calabcks.
   */

  @Test
  public void testConflationCreateUpdate() throws Exception {
    server1.invoke(putFromServer(KEY1, VALUE1));
    server1.invoke(putFromServer(KEY1, VALUE2));
    server1.invoke(putFromServer(LAST_KEY, LAST_VALUE));
    expectedNoEvents = 2;
    client1.invoke(checkNoEvents(expectedNoEvents));

  }

  /**
   * In this test do create , then update & update. The client should receive 2 callbacks , one for
   * create & one for the last update.
   */
  @Test
  public void testConflationUpdate() throws Exception {

    server1.invoke(putFromServer(KEY1, VALUE1));
    server1.invoke(putFromServer(KEY1, VALUE2));
    server1.invoke(putFromServer(KEY1, VALUE3));
    server1.invoke(putFromServer(KEY1, VALUE1));
    server1.invoke(putFromServer(KEY1, VALUE2));
    server1.invoke(putFromServer(KEY1, VALUE3));
    server1.invoke(putFromServer(KEY1, VALUE1));
    server1.invoke(putFromServer(KEY1, VALUE2));
    server1.invoke(putFromServer(KEY1, VALUE3));
    server1.invoke(putFromServer(LAST_KEY, LAST_VALUE));
    expectedNoEvents = 2;
    client1.invoke(checkNoEvents(expectedNoEvents));

  }

  /**
   * In this test do create , then update, update, invalidate. The client should receive 3
   * callbacks, one for create one for the last update and one for the invalidate.
   */
  @Test
  public void testConflationCreateUpdateInvalidate() throws Exception {

    server1.invoke(putFromServer(KEY1, VALUE1));
    server1.invoke(putFromServer(KEY1, VALUE2));
    server1.invoke(putFromServer(KEY1, VALUE3));
    server1.invoke(invalidateFromServer(KEY1));
    server1.invoke(putFromServer(LAST_KEY, LAST_VALUE));
    expectedNoEvents = 3;
    client1.invoke(checkNoEvents(expectedNoEvents));

  }

  /**
   * In this test do a create , update , update & destroy. The client should receive 3 callbacks (
   * craete , conflated update & destroy).
   */
  @Test
  public void testConflationCreateUpdateDestroy() throws Exception {

    server1.invoke(putFromServer(KEY1, VALUE1));
    server1.invoke(putFromServer(KEY1, VALUE2));
    server1.invoke(putFromServer(KEY1, VALUE3));
    server1.invoke(destroyFromServer(KEY1));
    server1.invoke(putFromServer(LAST_KEY, LAST_VALUE));
    expectedNoEvents = 3;
    client1.invoke(checkNoEvents(expectedNoEvents));

  }

  private CacheSerializableRunnable putFromServer(final String key, final String value) {
    CacheSerializableRunnable performPut = new CacheSerializableRunnable("putFromServer") {
      @Override
      public void run2() throws CacheException {
        Region region = basicGetCache().getRegion(Region.SEPARATOR + regionName);
        assertNotNull(region);
        basicGetCache().getLogger().info("starting put()");
        region.put(key, value);
        basicGetCache().getLogger().info("finished put()");
      }
    };

    return performPut;
  }

  private CacheSerializableRunnable invalidateFromServer(final String key) {
    CacheSerializableRunnable performInvalidate =
        new CacheSerializableRunnable("invalidateFromServer") {
          @Override
          public void run2() throws CacheException {
            Region region = basicGetCache().getRegion(Region.SEPARATOR + regionName);
            assertNotNull(region);
            region.invalidate(key);
            basicGetCache().getLogger().info("done invalidate() successfully");

          }
        };

    return performInvalidate;
  }

  private CacheSerializableRunnable destroyFromServer(final String key) {
    CacheSerializableRunnable performDestroy = new CacheSerializableRunnable("performDestroy") {
      @Override
      public void run2() throws CacheException {
        Region region = basicGetCache().getRegion(Region.SEPARATOR + regionName);
        assertNotNull(region);
        region.destroy(key);
        basicGetCache().getLogger().info("done destroy successfully");

      }
    };

    return performDestroy;
  }

  private CacheSerializableRunnable checkNoEvents(final int expectedEvents) {
    CacheSerializableRunnable checkEvents = new CacheSerializableRunnable("checkEvents") {
      final int interval = 200; // millis

      @Override
      public void run2() throws CacheException {
        WaitCriterion w = new WaitCriterion() {
          @Override
          public boolean done() {
            synchronized (LOCK) {

              if (!lastKeyArrived) {
                try {
                  LOCK.wait(interval);
                } catch (InterruptedException e) {
                  fail("interrupted");
                }
              }
            }
            return lastKeyArrived;
          }

          @Override
          public String description() {
            return "expected " + expectedEvents + " events but received " + actualNoEvents;
          }
        };

        GeodeAwaitility.await().untilAsserted(w);
      }
    };
    return checkEvents;
  }

  public static void makeDispatcherSlow() {

    System.setProperty("slowStartTimeForTesting", "15000");

  }

  private void createCache(Properties props) throws Exception {
    DistributedSystem ds = getSystem(props);
    assertNotNull(ds);
    ds.disconnect();
    ds = getSystem(props);
    getCache();
    assertNotNull(basicGetCache());
  }

  public static void createClientCache(String host, Integer port1, Boolean isListenerPresent)
      throws Exception {
    int PORT1 = port1.intValue();
    Properties props = new Properties();
    props.setProperty(MCAST_PORT, "0");
    props.setProperty(LOCATORS, "");
    new HAConflationDUnitTest().createCache(props);
    AttributesFactory factory = new AttributesFactory();
    ClientServerTestCase.configureConnectionPool(factory, host, new int[] {PORT1}, true, -1, -1,
        null);
    factory.setScope(Scope.DISTRIBUTED_ACK);
    factory.setEnableConflation(true);
    if (isListenerPresent.booleanValue() == true) {
      CacheListener clientListener = new HAClientCountEventListener();
      factory.setCacheListener(clientListener);
    }
    RegionAttributes attrs = factory.create();
    basicGetCache().createRegion(regionName, attrs);
    Region region = basicGetCache().getRegion(Region.SEPARATOR + regionName);
    assertNotNull(region);

    region.registerInterest(KEY1);
    region.registerInterest(KEY2);
    region.registerInterest(KEY3);
    region.registerInterest(LAST_KEY);
    lastKeyArrived = false;
    actualNoEvents = 0;

  }

  public static Integer createServerCache(Boolean isListenerPresent) throws Exception {
    new HAConflationDUnitTest().createCache(new Properties());
    AttributesFactory factory = new AttributesFactory();
    factory.setScope(Scope.DISTRIBUTED_ACK);
    factory.setEnableConflation(true);
    factory.setDataPolicy(DataPolicy.REPLICATE);
    if (isListenerPresent.booleanValue() == true) {
      CacheListener serverListener = new HAClientCountEventListener();
      factory.setCacheListener(serverListener);
    }
    RegionAttributes attrs = factory.create();
    basicGetCache().createRegion(regionName, attrs);
    CacheServerImpl server = (CacheServerImpl) basicGetCache().addCacheServer();
    assertNotNull(server);
    int port = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET);
    server.setPort(port);
    server.setNotifyBySubscription(true);
    server.start();
    return new Integer(server.getPort());
  }

  private static class HAClientCountEventListener implements CacheListener, Declarable {

    @Override
    public void afterCreate(EntryEvent event) {
      String key = (String) event.getKey();
      if (key.equals(LAST_KEY)) {
        synchronized (LOCK) {
          lastKeyArrived = true;
          LOCK.notifyAll();
        }
      } else {
        actualNoEvents++;
      }

    }

    @Override
    public void afterUpdate(EntryEvent event) {

      actualNoEvents++;

    }

    @Override
    public void afterInvalidate(EntryEvent event) {

      actualNoEvents++;

    }

    @Override
    public void afterDestroy(EntryEvent event) {
      actualNoEvents++;

    }

    @Override
    public void afterRegionInvalidate(RegionEvent event) {
      // TODO Auto-generated method stub

    }

    @Override
    public void afterRegionDestroy(RegionEvent event) {
      // TODO Auto-generated method stub

    }

    @Override
    public void afterRegionClear(RegionEvent event) {
      // TODO Auto-generated method stub

    }

    @Override
    public void afterRegionCreate(RegionEvent event) {
      // TODO Auto-generated method stub

    }

    @Override
    public void afterRegionLive(RegionEvent event) {
      // TODO NOT Auto-generated method stub, added by vrao

    }


    @Override
    public void close() {
      // TODO Auto-generated method stub

    }

    @Override
    public void init(Properties props) {
      // TODO Auto-generated method stub

    }
  }
}
