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

import static org.apache.geode.internal.process.ProcessUtils.identifyPid;
import static org.apache.geode.management.internal.MBeanJMXAdapter.getDistributedLockServiceName;
import static org.apache.geode.management.internal.MBeanJMXAdapter.getLockServiceMBeanName;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;

import javax.management.ObjectName;

import org.junit.Rule;
import org.junit.Test;

import org.apache.geode.distributed.DistributedLockService;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.locks.DLockService;
import org.apache.geode.management.internal.SystemManagementService;
import org.apache.geode.test.awaitility.GeodeAwaitility;
import org.apache.geode.test.dunit.VM;


@SuppressWarnings({"serial", "unused"})
public class DLockManagementDUnitTest implements Serializable {

  private static final int MAX_WAIT_MILLIS = 2 * 60 * 1000; // 2 MINUTES

  private static final String LOCK_SERVICE_NAME =
      DLockManagementDUnitTest.class.getSimpleName() + "_testLockService";

  @Member
  private VM[] memberVMs;

  @Manager
  private VM managerVM;

  @Rule
  public ManagementTestRule managementTestRule =
      ManagementTestRule.builder().defineManagersFirst(false).start(true).build();

  @Test
  public void testLockServiceMXBean() throws Throwable {
    createLockServiceGrantor(this.memberVMs[0]);
    createLockService(this.memberVMs[1]);
    createLockService(this.memberVMs[2]);

    for (VM memberVM : this.memberVMs) {
      verifyLockServiceMXBeanInMember(memberVM);
    }
    verifyLockServiceMXBeanInManager(this.managerVM);

    for (VM memberVM : this.memberVMs) {
      closeLockService(memberVM);
    }
  }

  @Test
  public void testDistributedLockServiceMXBean() throws Throwable {
    createLockServiceGrantor(this.memberVMs[0]);
    createLockService(this.memberVMs[1]);
    createLockService(this.memberVMs[2]);

    verifyDistributedLockServiceMXBean(this.managerVM, 3);

    DistributedMember member = this.managementTestRule.getDistributedMember(this.memberVMs[2]);
    verifyFetchOperations(this.managerVM, member);

    createLockService(this.managerVM);
    verifyDistributedLockServiceMXBean(this.managerVM, 4);

    for (VM memberVM : this.memberVMs) {
      closeLockService(memberVM);
    }
    verifyProxyCleanupInManager(this.managerVM);
    verifyDistributedLockServiceMXBean(this.managerVM, 1);

    closeLockService(this.managerVM);
    verifyDistributedLockServiceMXBean(this.managerVM, 0);
  }

  private void verifyProxyCleanupInManager(final VM managerVM) {
    managerVM.invoke("verifyProxyCleanupInManager", () -> {
      Set<DistributedMember> otherMembers = this.managementTestRule.getOtherNormalMembers();
      SystemManagementService service = this.managementTestRule.getSystemManagementService();

      for (final DistributedMember member : otherMembers) {
        ObjectName objectName = service.getRegionMBeanName(member, LOCK_SERVICE_NAME);
        GeodeAwaitility.await()
            .untilAsserted(() -> assertThat(lockServiceMXBeanIsGone(service, objectName)).isTrue());
      }
    });
  }

  private boolean lockServiceMXBeanIsGone(final SystemManagementService service,
      final ObjectName objectName) {
    return service.getMBeanProxy(objectName, LockServiceMXBean.class) == null;
  }

  private void createLockServiceGrantor(final VM memberVM) {
    memberVM.invoke("createLockServiceGrantor", () -> {
      assertThat(DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME)).isNull();

      DLockService lockService = (DLockService) DistributedLockService.create(LOCK_SERVICE_NAME,
          this.managementTestRule.getCache().getDistributedSystem());
      DistributedMember grantor = lockService.getLockGrantorId().getLockGrantorMember();
      assertThat(grantor).isNotNull();

      LockServiceMXBean lockServiceMXBean = awaitLockServiceMXBean(LOCK_SERVICE_NAME);

      assertThat(lockServiceMXBean).isNotNull();
      assertThat(lockServiceMXBean.isDistributed()).isTrue();
      assertThat(lockServiceMXBean.getName()).isEqualTo(LOCK_SERVICE_NAME);
      assertThat(lockServiceMXBean.isLockGrantor()).isTrue();
      assertThat(lockServiceMXBean.fetchGrantorMember())
          .isEqualTo(this.managementTestRule.getDistributedMember().getId());
    });
  }

  private void createLockService(final VM anyVM) {
    anyVM.invoke("createLockService", () -> {
      assertThat(DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME)).isNull();

      DistributedLockService.create(LOCK_SERVICE_NAME,
          this.managementTestRule.getCache().getDistributedSystem());

      LockServiceMXBean lockServiceMXBean = awaitLockServiceMXBean(LOCK_SERVICE_NAME);

      assertThat(lockServiceMXBean).isNotNull();
      assertThat(lockServiceMXBean.isDistributed()).isTrue();
      assertThat(lockServiceMXBean.isLockGrantor()).isFalse();
    });
  }

  private void closeLockService(final VM anyVM) {
    anyVM.invoke("closeLockService", () -> {
      assertThat(DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME)).isNotNull();
      DistributedLockService.destroy(LOCK_SERVICE_NAME);

      awaitLockServiceMXBeanIsNull(LOCK_SERVICE_NAME);

      ManagementService service = this.managementTestRule.getManagementService();
      LockServiceMXBean lockServiceMXBean = service.getLocalLockServiceMBean(LOCK_SERVICE_NAME);
      assertThat(lockServiceMXBean).isNull();
    });
  }

  private void verifyLockServiceMXBeanInMember(final VM memberVM) {
    memberVM.invoke("verifyLockServiceMXBeanInManager", () -> {
      DistributedLockService lockService =
          DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME);
      lockService.lock("lockObject_" + identifyPid(), MAX_WAIT_MILLIS, -1);

      ManagementService service = this.managementTestRule.getManagementService();
      LockServiceMXBean lockServiceMXBean = service.getLocalLockServiceMBean(LOCK_SERVICE_NAME);
      assertThat(lockServiceMXBean).isNotNull();

      String[] listHeldLock = lockServiceMXBean.listHeldLocks();
      assertThat(listHeldLock).hasSize(1);

      Map<String, String> lockThreadMap = lockServiceMXBean.listThreadsHoldingLock();
      assertThat(lockThreadMap).hasSize(1);
    });
  }

  /**
   * Verify lock data from remote Managing node
   */
  private void verifyLockServiceMXBeanInManager(final VM managerVM) throws Exception {
    managerVM.invoke("verifyLockServiceMXBeanInManager", () -> {
      Set<DistributedMember> otherMembers = this.managementTestRule.getOtherNormalMembers();

      for (DistributedMember member : otherMembers) {
        LockServiceMXBean lockServiceMXBean =
            awaitLockServiceMXBeanProxy(member, LOCK_SERVICE_NAME);
        assertThat(lockServiceMXBean).isNotNull();

        String[] listHeldLock = lockServiceMXBean.listHeldLocks();
        assertThat(listHeldLock).hasSize(1);

        Map<String, String> lockThreadMap = lockServiceMXBean.listThreadsHoldingLock();
        assertThat(lockThreadMap).hasSize(1);
      }
    });
  }

  private void verifyFetchOperations(final VM memberVM, final DistributedMember member) {
    memberVM.invoke("verifyFetchOperations", () -> {
      ManagementService service = this.managementTestRule.getManagementService();

      DistributedSystemMXBean distributedSystemMXBean = awaitDistributedSystemMXBean();
      ObjectName distributedLockServiceMXBeanName =
          getDistributedLockServiceName(LOCK_SERVICE_NAME);
      assertThat(distributedSystemMXBean.fetchDistributedLockServiceObjectName(LOCK_SERVICE_NAME))
          .isEqualTo(distributedLockServiceMXBeanName);

      ObjectName lockServiceMXBeanName = getLockServiceMBeanName(member.getId(), LOCK_SERVICE_NAME);
      assertThat(
          distributedSystemMXBean.fetchLockServiceObjectName(member.getId(), LOCK_SERVICE_NAME))
              .isEqualTo(lockServiceMXBeanName);
    });
  }

  /**
   * Verify Aggregate MBean
   */
  private void verifyDistributedLockServiceMXBean(final VM managerVM, final int memberCount) {
    managerVM.invoke("verifyDistributedLockServiceMXBean", () -> {
      ManagementService service = this.managementTestRule.getManagementService();

      if (memberCount == 0) {
        GeodeAwaitility.await().untilAsserted(
            () -> assertThat(service.getDistributedLockServiceMXBean(LOCK_SERVICE_NAME)).isNull());
        return;
      }

      DistributedLockServiceMXBean distributedLockServiceMXBean =
          awaitDistributedLockServiceMXBean(LOCK_SERVICE_NAME, memberCount);
      assertThat(distributedLockServiceMXBean).isNotNull();
      assertThat(distributedLockServiceMXBean.getName()).isEqualTo(LOCK_SERVICE_NAME);
    });
  }

  private DistributedSystemMXBean awaitDistributedSystemMXBean() {
    ManagementService service = this.managementTestRule.getManagementService();

    GeodeAwaitility.await()
        .untilAsserted(() -> assertThat(service.getDistributedSystemMXBean()).isNotNull());

    return service.getDistributedSystemMXBean();
  }

  /**
   * Await and return a DistributedRegionMXBean proxy with specified member count.
   */
  private DistributedLockServiceMXBean awaitDistributedLockServiceMXBean(
      final String lockServiceName, final int memberCount) {
    ManagementService service = this.managementTestRule.getManagementService();

    GeodeAwaitility.await().untilAsserted(() -> {
      assertThat(service.getDistributedLockServiceMXBean(lockServiceName)).isNotNull();
      assertThat(service.getDistributedLockServiceMXBean(lockServiceName).getMemberCount())
          .isEqualTo(memberCount);
    });

    return service.getDistributedLockServiceMXBean(lockServiceName);
  }

  /**
   * Await and return a LockServiceMXBean proxy for a specific member and lockServiceName.
   */
  private LockServiceMXBean awaitLockServiceMXBeanProxy(final DistributedMember member,
      final String lockServiceName) {
    SystemManagementService service = this.managementTestRule.getSystemManagementService();
    ObjectName lockServiceMXBeanName = service.getLockServiceMBeanName(member, lockServiceName);

    GeodeAwaitility.await().untilAsserted(
        () -> assertThat(service.getMBeanProxy(lockServiceMXBeanName, LockServiceMXBean.class))
            .isNotNull());

    return service.getMBeanProxy(lockServiceMXBeanName, LockServiceMXBean.class);
  }

  /**
   * Await creation of local LockServiceMXBean for specified lockServiceName.
   */
  private LockServiceMXBean awaitLockServiceMXBean(final String lockServiceName) {
    SystemManagementService service = this.managementTestRule.getSystemManagementService();

    GeodeAwaitility.await().untilAsserted(
        () -> assertThat(service.getLocalLockServiceMBean(lockServiceName)).isNotNull());

    return service.getLocalLockServiceMBean(lockServiceName);
  }

  /**
   * Await destruction of local LockServiceMXBean for specified lockServiceName.
   */
  private void awaitLockServiceMXBeanIsNull(final String lockServiceName) {
    SystemManagementService service = this.managementTestRule.getSystemManagementService();

    GeodeAwaitility.await().untilAsserted(
        () -> assertThat(service.getLocalLockServiceMBean(lockServiceName)).isNull());
  }

}
