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

import static org.assertj.core.api.Assertions.assertThat;

import java.util.ArrayList;
import java.util.List;

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

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
import org.apache.geode.management.internal.i18n.CliStrings;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.assertions.CommandResultAssert;
import org.apache.geode.test.junit.assertions.TabularResultModelAssert;
import org.apache.geode.test.junit.rules.GfshCommandRule;

public class RepeatedRebalanceDUnitTest {
  private static final String PARENT_REGION = "RepeatedRebalanceTestRegion";
  private static final String COLOCATED_REGION_ONE = "RepeatedRebalanceColocatedRegionOne";
  private static final String COLOCATED_REGION_TWO = "RepeatedRebalanceColocatedRegionTwo";
  private static final String PARTITION_RESOLVER =
      "org.apache.geode.management.internal.cli.commands.RepeatedRebalancePartitionResolver";

  private static final int TOTAL_NUM_BUCKETS = 48;
  private static final int NUM_REDUNDANT_COPIES = 2;
  private static final int INITIAL_SERVERS = 4;
  private static final int NUMBER_OF_ENTRIES = 30000;

  private List<MemberVM> memberList = new ArrayList<>();
  private MemberVM locator1;

  @Rule
  public GfshCommandRule gfsh = new GfshCommandRule();

  @Rule
  public ClusterStartupRule cluster = new ClusterStartupRule();


  @Before
  public void before() throws Exception {

    locator1 = cluster.startLocatorVM(0);

    for (int i = 0; i < INITIAL_SERVERS; ++i) {
      memberList.add(cluster.startServerVM(i + 1, locator1.getPort()));
    }

    gfsh.connectAndVerify(locator1);

    gfsh.executeAndAssertThat("create region --name=" + PARENT_REGION
        + " --type=PARTITION --redundant-copies=" + NUM_REDUNDANT_COPIES
        + " --enable-statistics=true "
        + "--recovery-delay=-1 --startup-recovery-delay=-1 --total-num-buckets=" + TOTAL_NUM_BUCKETS
        + " --partition-resolver=" + PARTITION_RESOLVER)
        .statusIsSuccess();

    gfsh.executeAndAssertThat("create region --name=" + COLOCATED_REGION_ONE
        + " --type=PARTITION --redundant-copies=" + NUM_REDUNDANT_COPIES
        + " --enable-statistics=true "
        + "--recovery-delay=-1 --startup-recovery-delay=-1 --total-num-buckets=" + TOTAL_NUM_BUCKETS
        + " --partition-resolver=" + PARTITION_RESOLVER
        + " --colocated-with=" + PARENT_REGION)
        .statusIsSuccess();

    gfsh.executeAndAssertThat("create region --name=" + COLOCATED_REGION_TWO
        + " --type=PARTITION --redundant-copies=" + NUM_REDUNDANT_COPIES
        + " --enable-statistics=true "
        + "--recovery-delay=-1 --startup-recovery-delay=-1 --total-num-buckets=" + TOTAL_NUM_BUCKETS
        + " --partition-resolver=" + PARTITION_RESOLVER
        + " --colocated-with=" + COLOCATED_REGION_ONE)
        .statusIsSuccess();
  }

  @Test
  public void testSecondRebalanceIsNotNecessaryWithAddedMembers() {
    addDataToRegion(NUMBER_OF_ENTRIES);

    addOrRestartServers(2, 0);

    CommandResultAssert firstRebalance = gfsh.executeAndAssertThat("rebalance").statusIsSuccess();

    String parentRegionTableSection = "";
    for (int i = 0; i < 3; i++) {
      if (firstRebalance.hasTableSection("Table" + i).getActual().getHeader()
          .contains(PARENT_REGION)) {
        parentRegionTableSection = "Table" + i;
      }
    }

    TabularResultModelAssert parentRegionTable =
        firstRebalance.hasTableSection(parentRegionTableSection);
    assertRedundancyNotChanged(parentRegionTable);
    assertBucketsMoved(parentRegionTable);
    assertPrimariesTransfered(parentRegionTable);

    CommandResultAssert secondRebalance =
        gfsh.executeAndAssertThat("rebalance").statusIsSuccess();

    for (int i = 0; i < 3; i++) {
      if (secondRebalance.hasTableSection("Table" + i).getActual().getHeader()
          .contains(PARENT_REGION)) {
        parentRegionTableSection = "Table" + i;
      }
    }

    parentRegionTable = secondRebalance.hasTableSection(parentRegionTableSection);
    assertRedundancyNotChanged(parentRegionTable);
    assertBucketsNotMoved(parentRegionTable);
    assertPrimariesNotTransfered(parentRegionTable);
  }

  @Test
  public void testSecondRebalanceIsNotNecessaryWithAddedAndRestartedMembers() {

    addDataToRegion(NUMBER_OF_ENTRIES);

    addOrRestartServers(2, 1);

    CommandResultAssert firstRebalance = gfsh.executeAndAssertThat("rebalance").statusIsSuccess();

    String parentRegionTableSection = "";
    for (int i = 0; i < 3; i++) {
      if (firstRebalance.hasTableSection("Table" + i).getActual().getHeader()
          .contains(PARENT_REGION)) {
        parentRegionTableSection = "Table" + i;
      }
    }

    TabularResultModelAssert parentRegionTable =
        firstRebalance.hasTableSection(parentRegionTableSection);
    assertRedundancyChanged(parentRegionTable);
    assertBucketsMoved(parentRegionTable);
    assertPrimariesTransfered(parentRegionTable);

    CommandResultAssert secondRebalance =
        gfsh.executeAndAssertThat("rebalance").statusIsSuccess();

    for (int i = 0; i < 3; i++) {
      if (secondRebalance.hasTableSection("Table" + i).getActual().getHeader()
          .contains(PARENT_REGION)) {
        parentRegionTableSection = "Table" + i;
      }
    }

    parentRegionTable = secondRebalance.hasTableSection(parentRegionTableSection);
    assertRedundancyNotChanged(parentRegionTable);
    assertBucketsNotMoved(parentRegionTable);
    assertPrimariesNotTransfered(parentRegionTable);
  }

  public void addDataToRegion(int entriesToAdd) {
    memberList.get(0).invoke(() -> {
      Cache cache = ClusterStartupRule.getCache();
      assertThat(cache).isNotNull();
      Region<String, String> region = cache.getRegion(PARENT_REGION);
      Region<String, String> colocatedRegionOne = cache.getRegion(COLOCATED_REGION_ONE);
      Region<String, String> colocatedRegionTwo = cache.getRegion(COLOCATED_REGION_TWO);

      for (int i = 0; i < entriesToAdd; i++) {
        region.put("key" + i, "value" + i);
        colocatedRegionOne.put("key" + i, "value" + i);
        colocatedRegionTwo.put("key" + i, "value" + i);
      }
    });
  }

  public void addOrRestartServers(int serversToAdd, int serversToRestart) {
    for (int i = 0; i < serversToAdd; ++i) {
      memberList.add(cluster.startServerVM(INITIAL_SERVERS + i, locator1.getPort()));
    }

    for (int i = 0; i < serversToRestart; ++i) {
      if (i < INITIAL_SERVERS && i < memberList.size()) {
        memberList.get(i).stop(false);
        memberList.remove(i);
        memberList.add(i, cluster.startServerVM(i + 1, locator1.getPort()));
      }
    }
  }

  // The following methods are provided to allow easier examination of the output of the rebalance
  // command
  private void assertRedundancyChanged(TabularResultModelAssert tabularResultModelAssert) {
    tabularResultModelAssert.hasRow(0).asList()
        .contains(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATEBYTES).last().isNotEqualTo("0");
    tabularResultModelAssert.hasRow(1).asList()
        .contains(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATETIM).last().isNotEqualTo("0");
    tabularResultModelAssert.hasRow(2).asList()
        .contains(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATESCOMPLETED).last().isNotEqualTo("0");
  }

  private void assertRedundancyNotChanged(TabularResultModelAssert tabularResultModelAssert) {
    tabularResultModelAssert.hasRow(0)
        .containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATEBYTES, "0");
    tabularResultModelAssert.hasRow(1)
        .containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATETIM, "0");
    tabularResultModelAssert.hasRow(2)
        .containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATESCOMPLETED, "0");
  }

  private void assertBucketsMoved(TabularResultModelAssert tabularResultModelAssert) {
    tabularResultModelAssert.hasRow(3).asList()
        .contains(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERBYTES).last().isNotEqualTo("0");
    tabularResultModelAssert.hasRow(4).asList()
        .contains(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERTIME).last().isNotEqualTo("0");
    tabularResultModelAssert.hasRow(5).asList()
        .contains(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERSCOMPLETED).last()
        .isNotEqualTo("0");
  }

  private void assertBucketsNotMoved(TabularResultModelAssert tabularResultModelAssert) {
    tabularResultModelAssert.hasRow(3)
        .containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERBYTES, "0");
    tabularResultModelAssert.hasRow(4)
        .containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERTIME, "0");
    tabularResultModelAssert.hasRow(5)
        .containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERSCOMPLETED, "0");
  }

  private void assertPrimariesTransfered(TabularResultModelAssert tabularResultModelAssert) {
    tabularResultModelAssert.hasRow(6).asList()
        .contains(CliStrings.REBALANCE__MSG__TOTALPRIMARYTRANSFERTIME).last().isNotEqualTo("0");
    tabularResultModelAssert.hasRow(7).asList()
        .contains(CliStrings.REBALANCE__MSG__TOTALPRIMARYTRANSFERSCOMPLETED).last()
        .isNotEqualTo("0");
  }

  private void assertPrimariesNotTransfered(TabularResultModelAssert tabularResultModelAssert) {
    tabularResultModelAssert.hasRow(6)
        .containsExactly(CliStrings.REBALANCE__MSG__TOTALPRIMARYTRANSFERTIME, "0");
    tabularResultModelAssert.hasRow(7)
        .containsExactly(CliStrings.REBALANCE__MSG__TOTALPRIMARYTRANSFERSCOMPLETED, "0");
  }
}
