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

import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.INDEX_NAME;
import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.REGION_NAME;
import static org.apache.geode.test.awaitility.GeodeAwaitility.await;

import java.util.Set;
import java.util.stream.IntStream;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.control.RebalanceFactory;
import org.apache.geode.cache.control.RebalanceOperation;
import org.apache.geode.cache.control.RebalanceResults;
import org.apache.geode.cache.control.ResourceManager;
import org.apache.geode.cache.lucene.internal.LuceneIndexFactoryImpl;
import org.apache.geode.cache.lucene.internal.LuceneServiceImpl;
import org.apache.geode.cache.partition.PartitionMemberInfo;
import org.apache.geode.cache.partition.PartitionRebalanceInfo;
import org.apache.geode.cache.partition.PartitionRegionInfo;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.test.dunit.AsyncInvocation;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.SerializableRunnableIF;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.junit.categories.LuceneTest;

@Category({LuceneTest.class})
@RunWith(JUnitParamsRunner.class)
public class RebalanceWithRedundancyWithRegionCreatedBeforeReindexDUnitTest
    extends LuceneQueriesAccessorBase {

  private static final Logger logger = LogService.getLogger();

  protected VM dataStore3;
  protected VM dataStore4;

  @Override
  public void postSetUp() throws Exception {
    super.postSetUp();
    dataStore3 = Host.getHost(0).getVM(2);
    dataStore4 = Host.getHost(0).getVM(3);
  }

  @Before
  public void setNumBuckets() {
    NUM_BUCKETS = 113;
  }

  @Before
  public void setLuceneReindexFlag() {
    dataStore1.invoke(() -> LuceneServiceImpl.LUCENE_REINDEX = true);
    dataStore2.invoke(() -> LuceneServiceImpl.LUCENE_REINDEX = true);
    dataStore3.invoke(() -> LuceneServiceImpl.LUCENE_REINDEX = true);
    dataStore4.invoke(() -> LuceneServiceImpl.LUCENE_REINDEX = true);
  }

  @Override
  protected RegionTestableType[] getListOfRegionTestTypes() {
    return new RegionTestableType[] {RegionTestableType.PARTITION,
        RegionTestableType.PARTITION_REDUNDANT};
  }

  @After
  public void clearLuceneReindexFlag() {
    dataStore1.invoke(() -> LuceneServiceImpl.LUCENE_REINDEX = false);
    dataStore2.invoke(() -> LuceneServiceImpl.LUCENE_REINDEX = false);
    dataStore3.invoke(() -> LuceneServiceImpl.LUCENE_REINDEX = false);
    dataStore4.invoke(() -> LuceneServiceImpl.LUCENE_REINDEX = false);
  }

  protected SerializableRunnable createIndex = new SerializableRunnable("createIndex") {
    @Override
    public void run() {
      LuceneService luceneService = LuceneServiceProvider.get(getCache());
      ((LuceneIndexFactoryImpl) luceneService.createIndexFactory()).addField("text")
          .create(INDEX_NAME, REGION_NAME, LuceneServiceImpl.LUCENE_REINDEX);
    }
  };

  protected SerializableRunnable rebalance = new SerializableRunnable("rebalance") {
    @Override
    public void run() throws InterruptedException {
      Cache cache = getCache();
      cache.getRegion(REGION_NAME);

      ResourceManager resMan = cache.getResourceManager();
      RebalanceFactory factory = resMan.createRebalanceFactory();
      logger.info("Starting rebalance");
      RebalanceResults rebalanceResults = null;
      RebalanceOperation rebalanceOp = factory.start();
      rebalanceResults = rebalanceOp.getResults();
      await().until(() -> rebalanceOp.isDone());
      logger.info("Rebalance completed: "
          + RebalanceResultsToString(rebalanceResults, "Rebalance completed"));
    }
  };

  protected SerializableRunnable doConcOps = new SerializableRunnable("doConcOps") {
    @Override
    public void run() {
      putEntryInEachBucket(113);
    }
  };

  protected void createIndexAndRebalance(RegionTestableType regionTestType,
      SerializableRunnableIF createIndex, boolean doOps) throws Exception {

    // give rebalance some work to do by adding another vm
    // dataStore4.invoke(() -> (createIndex));
    dataStore4.invoke(() -> initDataStore(regionTestType));

    AsyncInvocation aiRebalancer = dataStore1.invokeAsync(rebalance);

    if (doOps) {
      AsyncInvocation aiConcOps = dataStore1.invokeAsync(doConcOps);
      aiConcOps.join();
      aiConcOps.checkException();
    }

    // re-index stored data
    AsyncInvocation ai1 = dataStore1.invokeAsync(createIndex);
    AsyncInvocation ai2 = dataStore2.invokeAsync(createIndex);
    AsyncInvocation ai3 = dataStore3.invokeAsync(createIndex);
    AsyncInvocation ai4 = dataStore4.invokeAsync(createIndex);

    aiRebalancer.join();
    aiRebalancer.checkException();

    ai1.join();
    ai2.join();
    ai3.join();
    ai4.join();

    ai1.checkException();
    ai2.checkException();
    ai3.checkException();
    ai4.checkException();

  }

  @Test
  @Parameters(method = "getListOfRegionTestTypes")
  public void returnCorrectResultsWithConcurrentOpsAndRebalance(RegionTestableType regionTestType)
      throws Exception {

    createAndPopulateRegion(regionTestType, NUM_BUCKETS / 2);

    createIndexAndRebalance(regionTestType, createIndex, true);

    waitForFlushBeforeExecuteTextSearch(dataStore3, 60000);
    executeTextSearch(dataStore3, "world", "text", NUM_BUCKETS);

  }

  private void createAndPopulateRegion(RegionTestableType regionTestType, int numEntries) {

    dataStore1.invoke(() -> initDataStore(regionTestType));
    dataStore2.invoke(() -> initDataStore(regionTestType));
    dataStore3.invoke(() -> initDataStore(regionTestType));

    putEntryInEachBucket(numEntries);
  }

  protected void putEntryInEachBucket(int numBuckets) {
    dataStore3.invoke(() -> {
      final Cache cache = getCache();
      Region<Object, Object> region = cache.getRegion(REGION_NAME);
      IntStream.range(0, numBuckets).forEach(i -> region.put(i, new TestObject("hello world")));
    });
  }

  public static String RebalanceResultsToString(RebalanceResults results, String title) {
    if (results == null) {
      return "null";
    }
    StringBuffer aStr = new StringBuffer();
    aStr.append("Rebalance results (" + title + ") totalTime: "
        + valueToString(results.getTotalTime()) + "\n");

    // bucketCreates
    aStr.append(
        "totalBucketCreatesCompleted: " + valueToString(results.getTotalBucketCreatesCompleted()));
    aStr.append(" totalBucketCreateBytes: " + valueToString(results.getTotalBucketCreateBytes()));
    aStr.append(
        " totalBucketCreateTime: " + valueToString(results.getTotalBucketCreateTime()) + "\n");

    // bucketTransfers
    aStr.append("totalBucketTransfersCompleted: "
        + valueToString(results.getTotalBucketTransfersCompleted()));
    aStr.append(
        " totalBucketTransferBytes: " + valueToString(results.getTotalBucketTransferBytes()));
    aStr.append(
        " totalBucketTransferTime: " + valueToString(results.getTotalBucketTransferTime()) + "\n");

    // primaryTransfers
    aStr.append("totalPrimaryTransfersCompleted: "
        + valueToString(results.getTotalPrimaryTransfersCompleted()));
    aStr.append(" totalPrimaryTransferTime: " + valueToString(results.getTotalPrimaryTransferTime())
        + "\n");

    // PartitionRebalanceDetails (per region)
    Set<PartitionRebalanceInfo> prdSet = results.getPartitionRebalanceDetails();
    for (PartitionRebalanceInfo prd : prdSet) {
      aStr.append(partitionRebalanceDetailsToString(prd));
    }
    aStr.append("total time (ms): " + valueToString(results.getTotalTime()));

    String returnStr = aStr.toString();
    return returnStr;
  }

  private static String partitionRebalanceDetailsToString(PartitionRebalanceInfo details) {
    if (details == null) {
      return "null\n";
    }

    StringBuffer aStr = new StringBuffer();
    aStr.append("PartitionedRegionDetails for region named " + getRegionName(details) + " time: "
        + valueToString(details.getTime()) + "\n");

    // bucketCreates
    aStr.append("bucketCreatesCompleted: " + valueToString(details.getBucketCreatesCompleted()));
    aStr.append(" bucketCreateBytes: " + valueToString(details.getBucketCreateBytes()));
    aStr.append(" bucketCreateTime: " + valueToString(details.getBucketCreateTime()) + "\n");

    // bucketTransfers
    aStr.append(
        "bucketTransfersCompleted: " + valueToString(details.getBucketTransfersCompleted()));
    aStr.append(" bucketTransferBytes: " + valueToString(details.getBucketTransferBytes()));
    aStr.append(" bucketTransferTime: " + valueToString(details.getBucketTransferTime()) + "\n");

    // primaryTransfers
    aStr.append(
        "PrimaryTransfersCompleted: " + valueToString(details.getPrimaryTransfersCompleted()));
    aStr.append(" PrimaryTransferTime: " + valueToString(details.getPrimaryTransferTime()) + "\n");

    // PartitionMemberDetails (before)
    aStr.append("PartitionedMemberDetails (before)\n");
    Set<PartitionMemberInfo> pmdSet = details.getPartitionMemberDetailsBefore();
    for (PartitionMemberInfo pmd : pmdSet) {
      aStr.append(partitionMemberDetailsToString(pmd));
    }

    // PartitionMemberDetails (after)
    aStr.append("PartitionedMemberDetails (after)\n");
    pmdSet = details.getPartitionMemberDetailsAfter();
    for (PartitionMemberInfo pmd : pmdSet) {
      aStr.append(partitionMemberDetailsToString(pmd));
    }

    return aStr.toString();
  }

  public static String partitionedRegionDetailsToString(PartitionRegionInfo prd) {

    if (prd == null) {
      return "null\n";
    }

    StringBuffer aStr = new StringBuffer();

    aStr.append("PartitionedRegionDetails for region named " + getRegionName(prd) + "\n");
    aStr.append("  configuredBucketCount: " + valueToString(prd.getConfiguredBucketCount()) + "\n");
    aStr.append("  createdBucketCount: " + valueToString(prd.getCreatedBucketCount()) + "\n");
    aStr.append(
        "  lowRedundancyBucketCount: " + valueToString(prd.getLowRedundancyBucketCount()) + "\n");
    aStr.append(
        "  configuredRedundantCopies: " + valueToString(prd.getConfiguredRedundantCopies()) + "\n");
    aStr.append("  actualRedundantCopies: " + valueToString(prd.getActualRedundantCopies()) + "\n");

    // memberDetails
    Set<PartitionMemberInfo> pmd = prd.getPartitionMemberInfo();
    for (PartitionMemberInfo memberDetails : pmd) {
      aStr.append(partitionMemberDetailsToString(memberDetails));
    }

    // colocatedWithDetails
    String colocatedWith = prd.getColocatedWith();
    aStr.append("  colocatedWith: " + colocatedWith + "\n");

    String returnStr = aStr.toString();
    return returnStr;
  }

  private static String partitionMemberDetailsToString(PartitionMemberInfo pmd) {
    StringBuffer aStr = new StringBuffer();
    long localMaxMemory = pmd.getConfiguredMaxMemory();
    long size = pmd.getSize();
    aStr.append("    Member Details for: " + pmd.getDistributedMember() + "\n");
    aStr.append("      configuredMaxMemory: " + valueToString(localMaxMemory));
    double inUse = (double) size / localMaxMemory;
    double heapUtilization = inUse * 100;
    aStr.append(" size: " + size + " (" + valueToString(heapUtilization) + "%)");
    aStr.append(" bucketCount: " + valueToString(pmd.getBucketCount()));
    aStr.append(" primaryCount: " + valueToString(pmd.getPrimaryCount()) + "\n");
    return aStr.toString();
  }

  /**
   * Convert the given long to a String; if it is negative then flag it in the string
   */
  private static String valueToString(long value) {
    String returnStr = "" + value;
    return returnStr;
  }

  /**
   * Convert the given double to a String; if it is negative then flag it in the string
   */
  private static String valueToString(double value) {
    String returnStr = "" + value;
    return returnStr;
  }

  public static String getRegionName(PartitionRegionInfo prd) {
    return prd.getRegionPath().substring(1);
  }

  public static String getRegionName(PartitionRebalanceInfo prd) {
    return prd.getRegionPath().substring(1);
  }
}
