/*
 * 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.distributed.internal;

import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED;
import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
import static org.assertj.core.api.Assertions.assertThat;

import java.net.InetAddress;
import java.util.Set;

import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.Scope;
import org.apache.geode.distributed.DistributedLockService;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.Config;
import org.apache.geode.internal.admin.Alert;
import org.apache.geode.internal.admin.AlertListener;
import org.apache.geode.internal.admin.ApplicationVM;
import org.apache.geode.internal.admin.DLockInfo;
import org.apache.geode.internal.admin.EntryValueNode;
import org.apache.geode.internal.admin.GemFireVM;
import org.apache.geode.internal.admin.GfManagerAgent;
import org.apache.geode.internal.admin.GfManagerAgentConfig;
import org.apache.geode.internal.admin.GfManagerAgentFactory;
import org.apache.geode.internal.admin.StatResource;
import org.apache.geode.internal.admin.remote.RemoteTransportConfig;
import org.apache.geode.internal.logging.InternalLogWriter;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.cache.CacheTestCase;

/**
 * This class tests the functionality of the {@linkplain org.apache.geode.internal.admin internal
 * admin} API.
 */

public class ClusterDistributionManagerForAdminDUnitTest extends CacheTestCase
    implements AlertListener {

  private static Logger logger = LogService.getLogger();

  private transient GfManagerAgent agent;

  @Before
  public void setUp() throws Exception {
    IgnoredException.addIgnoredException("Error occurred while reading system log");

    ClusterDistributionManager.setIsDedicatedAdminVM(true);

    populateCache();

    boolean created = !isConnectedToDS();
    InternalDistributedSystem ds = getSystem();
    RemoteTransportConfig transport =
        new RemoteTransportConfig(ds.getConfig(), ClusterDistributionManager.ADMIN_ONLY_DM_TYPE);
    if (created) {
      disconnectFromDS();
    }

    // create a GfManagerAgent in the master vm.
    this.agent = GfManagerAgentFactory.getManagerAgent(
        new GfManagerAgentConfig(null, transport, getLogWriter(), Alert.SEVERE, this, null));

    await().untilAsserted(() -> assertThat(agent.isConnected()).isTrue());
  }

  @Override
  @After
  public void preTearDownCacheTestCase() throws Exception {
    try {
      if (this.agent != null) {
        this.agent.disconnect();
      }
      disconnectFromDS();
    } finally {
      ClusterDistributionManager.setIsDedicatedAdminVM(false);
    }
  }

  @Test
  public void testGetDistributionVMType() {
    DistributionManager dm = this.agent.getDM();
    assertThat(dm.getId().getVmKind()).isEqualTo(ClusterDistributionManager.ADMIN_ONLY_DM_TYPE);
  }

  @Test
  public void testAgent() {
    assertThat(agent.listPeers()).hasSize(0);
    assertThat(agent.isConnected()).isTrue();
    agent.disconnect();
    assertThat(agent.isConnected()).isFalse();
  }

  @Test
  public void testApplications() throws Exception {
    await()
        .untilAsserted(() -> assertThat(agent.listApplications().length).isGreaterThanOrEqualTo(4));

    ApplicationVM[] applications = agent.listApplications();
    for (int whichApplication = 0; whichApplication < applications.length; whichApplication++) {

      InetAddress host = applications[whichApplication].getHost();
      String appHostName = host.getHostName();

      assertThat(host).isEqualTo(InetAddress.getByName(appHostName));

      StatResource[] stats = applications[whichApplication].getStats(null);
      assertThat(stats.length).isGreaterThan(0);

      Config config = applications[whichApplication].getConfig();
      String[] attributeNames = config.getAttributeNames();
      boolean foundStatisticSamplingEnabled = false;
      for (String attributeName : attributeNames) {
        if (attributeName.equals(STATISTIC_SAMPLING_ENABLED)) {
          foundStatisticSamplingEnabled = true;
          assertThat(config.getAttribute(attributeName)).isEqualTo("true");
          break;
        }
      }
      assertThat(foundStatisticSamplingEnabled).isTrue();

      String[] logs = applications[whichApplication].getSystemLogs();
      assertThat(logs.length).isGreaterThan(0);

      VM vm = findVMForAdminObject(applications[whichApplication]);
      assertThat(vm).isNotNull();

      String lockName = "cdm_testlock" + whichApplication;
      assertThat(acquireDistributedLock(vm, lockName)).isTrue();

      DLockInfo[] locks = applications[whichApplication].getDistributedLockInfo();
      assertThat(locks.length).isGreaterThan(0);

      boolean foundLock = false;
      for (DLockInfo lock : locks) {
        if (lock.getLockName().equals(lockName)) {
          foundLock = true;
          assertThat(lock.isAcquired()).isTrue();
        }
      }
      assertThat(foundLock).isTrue();

      Region[] roots = applications[whichApplication].getRootRegions();
      assertThat(roots.length).isGreaterThan(0);

      Region root = roots[0];
      assertThat(root).isNotNull();
      assertThat(root.getName()).isEqualTo("root");
      assertThat(root.getFullPath()).isEqualTo("/root");

      RegionAttributes attributes = root.getAttributes();
      assertThat(attributes).isNotNull();
      if (attributes.getStatisticsEnabled()) {
        assertThat(root.getStatistics()).isNotNull();
      }

      Set subregions = root.subregions(false);
      assertThat(subregions).hasSize(3);
      assertThat(root.keySet()).hasSize(2);

      Region.Entry entry = root.getEntry("cacheObj1");
      assertThat(entry).isNotNull();
      if (attributes.getStatisticsEnabled()) {
        assertThat(entry.getStatistics()).isNotNull();
      }
      assertThat(entry.getValue()).isEqualTo("null");

      /// test lightweight inspection;
      entry = root.getEntry("cacheObj2");
      assertThat(entry).isNotNull();

      Object val = entry.getValue();
      assertThat(val).isInstanceOf(String.class);
      assertThat(((String) val)).contains("java.lang.StringBuffer");

      /// test physical inspection
      applications[whichApplication].setCacheInspectionMode(GemFireVM.PHYSICAL_CACHE_VALUE);
      entry = root.getEntry("cacheObj2");
      assertThat(entry).isNotNull();

      val = entry.getValue();
      assertThat(val).isInstanceOf(EntryValueNode.class);

      EntryValueNode node = (EntryValueNode) val;
      String type = node.getType();
      assertThat(type).contains("java.lang.StringBuffer");
      assertThat(node.isPrimitiveOrString()).isFalse();

      EntryValueNode[] fields = node.getChildren();
      assertThat(fields).isNotNull();

      getLogWriter().warning(
          "The tests use StringBuffers for values which might be implemented differently in jdk 1.5");

      /// test destruction in the last valid app
      int lastApplication = applications.length - 1;
      if (whichApplication == lastApplication) {
        int expectedSize = subregions.size() - 1;
        Region subRegion = (Region) subregions.iterator().next();
        Region rootRegion = root;
        subRegion.destroyRegion();

        await()
            .untilAsserted(
                () -> assertThat(rootRegion.subregions(false).size()).isEqualTo(expectedSize));
      }
    }
  }

  @Override
  public void alert(Alert alert) {
    getLogWriter().info("DEBUG: alert=" + alert);
  }

  private void populateCache() {
    for (int i = 0; i < Host.getHostCount(); i++) {
      Host host = Host.getHost(i);

      for (int j = 0; j < host.getVMCount(); j++) {
        VM vm = host.getVM(j);
        vm.invoke(() -> {
          AttributesFactory attributesFactory = new AttributesFactory();
          attributesFactory.setScope(Scope.DISTRIBUTED_NO_ACK);

          RegionAttributes regionAttributes = attributesFactory.create();
          createRegion("cdm-testSubRegion1", regionAttributes);
          createRegion("cdm-testSubRegion2", regionAttributes);
          createRegion("cdm-testSubRegion3", regionAttributes);
          remoteCreateEntry("", "cacheObj1", null);
          StringBuffer val = new StringBuffer("userDefValue1");
          remoteCreateEntry("", "cacheObj2", val);
        });
      }
    }
  }

  /**
   * Puts (or creates) a value in a region named <code>regionName</code> named
   * <code>entryName</code>.
   */
  private void remoteCreateEntry(String regionName, String entryName, Object value)
      throws CacheException {

    Region root = getRootRegion();
    Region region = root.getSubregion(regionName);
    region.create(entryName, value);

    logger.info("Put value " + value + " in entry " + entryName + " in region '"
        + region.getFullPath() + "'");
  }

  private boolean acquireDistributedLock(VM vm, String lockName) {
    return vm.invoke(() -> remoteAcquireDistLock(lockName));
  }

  private boolean remoteAcquireDistLock(String lockName) {
    String serviceName = "cdmtest_service";
    DistributedLockService service = DistributedLockService.getServiceNamed(serviceName);
    if (service == null) {
      service =
          DistributedLockService.create(serviceName, InternalDistributedSystem.getAnyInstance());
    }
    assertThat(service).isNotNull();
    return service.lock(lockName, 1000, 3000);
  }

  private VM findVMForAdminObject(GemFireVM gemFireVM) {
    for (int i = 0; i < Host.getHostCount(); i++) {
      Host host = Host.getHost(i);
      for (int j = 0; j < host.getVMCount(); j++) {
        VM vm = host.getVM(j);
        InternalDistributedMember member = getJavaGroupsIdForVM(vm);
        if (gemFireVM.getId().equals(member)) {
          return vm;
        }
      }
    }
    return null;
  }

  private InternalDistributedMember getJavaGroupsIdForVM(VM vm) {
    return vm.invoke(() -> remoteGetJavaGroupsIdForVM());
  }

  private InternalDistributedMember remoteGetJavaGroupsIdForVM() {
    InternalDistributedSystem system = InternalDistributedSystem.getAnyInstance();
    return system.getDistributionManager().getDistributionManagerId();
  }

  private InternalLogWriter getLogWriter() {
    return (InternalLogWriter) getSystem().getLogWriter();
  }
}
