/*
 * 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.cache.Region.SEPARATOR;
import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPort;
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.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(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(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(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(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 = getRandomAvailableTCPPort();
    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

    }
  }
}
