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

#include <geode/CacheFactory.hpp>
#include <geode/Region.hpp>
#include <string>
#include <iostream>

#include "fw_helper.hpp"

using apache::geode::client::Cache;
using apache::geode::client::CacheFactory;
using apache::geode::client::CacheXmlException;
using apache::geode::client::DiskPolicyType;
using apache::geode::client::Exception;
using apache::geode::client::ExpirationAction;
using apache::geode::client::Region;

int testXmlCacheCreationWithOverflow() {
  auto cacheFactory = CacheFactory();
  std::shared_ptr<Cache> cptr;
  const uint32_t totalSubRegionsRoot1 = 2;
  const uint32_t totalRootRegions = 2;

  char *path = ACE_OS::getenv("TESTSRC");
  std::string directory(path);

  std::cout << "create DistributedSytem with name=XML_CACHE_CREATION_TEST"
            << std::endl;
  std::cout << "Create cache with the configurations provided in "
               "valid_overflowAttr.xml"
            << std::endl;

  try {
    std::string filePath = directory + "/resources/non-existent.xml";
    cptr = std::make_shared<Cache>(
        cacheFactory.set("cache-xml-file", filePath.c_str()).create());
    return -1;
  } catch (CacheXmlException &ex) {
    std::cout << "CacheXmlException: msg = " << ex.what() << std::endl;
    LOG(ex.getStackTrace());
  } catch (...) {
    LOGINFO("Unknown exception");
    return -1;
  }

  /// return 0;
  try {
    std::string filePath = directory + "/resources/valid_overflowAttr.xml";
    std::cout << "getPdxIgnoreUnreadFields should return true.1" << std::endl;
    cptr = std::make_shared<Cache>(
        cacheFactory.set("cache-xml-file", filePath.c_str()).create());
    if (cptr->getPdxIgnoreUnreadFields() != false) {
      std::cout << "getPdxIgnoreUnreadFields should return true." << std::endl;
      return -1;
    } else {
      std::cout << "getPdxIgnoreUnreadFields returned true." << std::endl;
    }
    // return 0;
  } catch (Exception &ex) {
    std::cout << "getPdxIgnoreUnreadFields should return true2." << std::endl;
    std::cout << "Exception: msg = " << ex.what() << std::endl;
    LOG(ex.getStackTrace());
    return -1;
  } catch (...) {
    LOGINFO(" unknown exception");
    return -1;
  }

  std::cout << "Test if number of root regions are correct" << std::endl;
  auto vrp = cptr->rootRegions();
  std::cout << "  vrp.size=" << vrp.size() << std::endl;

  if (vrp.size() != totalRootRegions) {
    std::cout << "Number of root regions does not match" << std::endl;
    return -1;
  }

  std::cout << "Root regions in Cache :" << std::endl;
  for (size_t i = 0; i < vrp.size(); i++) {
    std::cout << "vc[" << i << "].m_reaPtr=" << vrp.at(i).get() << std::endl;
    std::cout << "vc[" << i << "]=" << vrp.at(i)->getName() << std::endl;
  }
  auto regPtr1 = vrp.at(0);

  std::cout
      << "Test if the number of sub regions with the root region Root1 are "
         "correct"
      << std::endl;
  std::vector<std::shared_ptr<Region>> vr = regPtr1->subregions(true);
  std::cout << "  vr.size=" << vr.size() << std::endl;
  if (vr.size() != totalSubRegionsRoot1) {
    std::cout << "Number of Subregions does not match" << std::endl;
    return -1;
  }

  std::cout << "get subregions from the root region :" << vrp.at(0)->getName()
            << std::endl;
  for (size_t i = 0; i < vr.size(); i++) {
    std::cout << "vc[" << i << "].m_reaPtr=" << vr.at(i).get() << std::endl;
    std::cout << "vc[" << i << "]=" << vr.at(i)->getName() << std::endl;
  }

  std::cout << "Test if the nesting of regions is correct" << std::endl;
  auto regPtr2 = vrp.at(1);
  auto &&vsr = regPtr2->subregions(true);
  for (auto &&regPtr : vsr) {
    auto &&childName = regPtr->getName();
    auto &&parentName = regPtr->getParentRegion()->getName();
    if (childName == "SubSubRegion221") {
      if (parentName != "SubRegion22") {
        std::cout << "Incorrect parent: tree structure not formed correctly"
                  << std::endl;
        return -1;
      }
    }
  }
  std::cout
      << "****Correct region tree structure created from valid_cache.xml****"
      << std::endl;

  vr.clear();
  vrp.clear();

  std::cout << "Test the attributes of region" << std::endl;

  auto regionAttributes = regPtr1->getAttributes();
  std::cout << "Attributes of root region Root1 are : " << std::endl;

  bool cachingEnabled = regionAttributes.getCachingEnabled();
  std::cout << "Caching-enabled :true" << std::endl;
  if (!cachingEnabled) {
    return -1;
  }
  int lruEL = regionAttributes.getLruEntriesLimit();
  std::cout << "lru-entries-limit : 35" << std::endl;
  if (lruEL != 35) {
    return -1;
  }
  int concurrency = regionAttributes.getConcurrencyLevel();
  std::cout << "concurrency-level : 10" << std::endl;
  if (concurrency != 10) {
    return -1;
  }
  int initialCapacity = regionAttributes.getInitialCapacity();
  std::cout << "initial-capacity : 25" << std::endl;
  if (initialCapacity != 25) {
    return -1;
  }
  auto regionIdleTO = regionAttributes.getRegionIdleTimeout().count();
  std::cout << "RegionIdleTimeout:20 " << std::endl;
  if (regionIdleTO != 20) {
    return -1;
  }

  ExpirationAction action1 = regionAttributes.getRegionIdleTimeoutAction();
  std::cout << "RegionIdleTimeoutAction : Destroy" << std::endl;
  if (action1 != ExpirationAction::DESTROY) {
    return -1;
  }
  const DiskPolicyType type = regionAttributes.getDiskPolicy();
  std::cout << "DiskPolicy : overflows" << std::endl;
  if (type != DiskPolicyType::OVERFLOWS) {
    std::cout << " diskpolicy is not overflows " << std::endl;
    return -1;
  }

  std::cout << "persistence library = "
            << regionAttributes.getPersistenceLibrary() << std::endl;
  std::cout << "persistence function = "
            << regionAttributes.getPersistenceFactory() << std::endl;
  auto pconfig = regionAttributes.getPersistenceProperties();
  if (pconfig != nullptr) {
    std::cout << " persistence property is not null" << std::endl;
    std::cout << " persistencedir = "
              << pconfig->find("PersistenceDirectory")->value().c_str()
              << std::endl;
    std::cout << " pagesize = " << pconfig->find("PageSize")->value().c_str()
              << std::endl;
    std::cout << " maxpagecount = "
              << pconfig->find("MaxPageCount")->value().c_str() << std::endl;
  }
  std::cout << "****Attributes of Root1 are correctly set****" << std::endl;

  auto regionAttributes2 = regPtr2->getAttributes();
  std::cout << "persistence library = "
            << regionAttributes2.getPersistenceLibrary() << std::endl;
  std::cout << "persistence function = "
            << regionAttributes2.getPersistenceFactory() << std::endl;
  auto pconfig2 = regionAttributes2.getPersistenceProperties();
  if (pconfig2 != nullptr) {
    std::cout << " persistence property is not null for Root2" << std::endl;
    std::cout << " persistencedir2 = "
              << pconfig2->find("PersistenceDirectory")->value().c_str()
              << std::endl;
    std::cout << " pagesize2 = " << pconfig->find("PageSize")->value().c_str()
              << std::endl;
    std::cout << " maxpagecount2 = "
              << pconfig->find("MaxPageCount")->value().c_str() << std::endl;
  }
  std::cout << "Destroy region" << std::endl;
  try {
    regPtr1->localDestroyRegion();
    regPtr2->localDestroyRegion();
  } catch (Exception &ex) {
    std::cout << "Exception: msg = " << ex.what() << std::endl;
    LOG(ex.getStackTrace());
    return -1;
  }

  regPtr1 = nullptr;
  regPtr2 = nullptr;

  if (!cptr->isClosed()) {
    cptr->close();
    cptr = nullptr;
  }
  ////////////////////////////testing of cache.xml completed///////////////////

  std::cout << "Create cache with the configurations provided in the "
               "invalid_overflowAttr1.xml."
            << std::endl;
  std::cout << "This is a well-formed xml....attributes not provided for "
               "persistence manager. exception should be thrown"
            << std::endl;

  try {
    const auto filePath = directory + "/invalid_overflowAttr1.xml";
    cptr = std::make_shared<Cache>(
        cacheFactory.set("cache-xml-file", filePath).create());
    return -1;
  } catch (Exception &ex) {
    std::cout << std::endl;
    std::cout << "Exception: msg = " << ex.what() << std::endl;
    LOG(ex.getStackTrace());
  }

  ///////////////testing of invalid_cache1.xml completed///////////////////

  std::cout << "Create cache with the configurations provided in the "
               "invalid_overflowAttr2.xml."
            << std::endl;
  std::cout
      << " This is a well-formed xml....attribute values is not provided for "
         "persistence library name......should throw an exception"
      << std::endl;

  try {
    const auto filePath = directory + "/invalid_overflowAttr2.xml";
    cptr = std::make_shared<Cache>(
        cacheFactory.set("cache-xml-file", filePath).create());
    return -1;
  } catch (CacheXmlException &ex) {
    std::cout << std::endl;
    std::cout << "CacheXmlException: msg = " << ex.what() << std::endl;
    LOG(ex.getStackTrace());
  }

  ///////////////testing of invalid_cache2.xml completed///////////////////

  std::cout << "Create cache with the configurations provided in the "
               "invalid_overflowAttr3.xml."
            << std::endl;

  std::cout
      << "This is a well-formed xml....but region-attributes for persistence "
         "invalid......should throw an exception"
      << std::endl;

  try {
    const auto filePath = directory + "/invalid_overflowAttr3.xml";
    cptr = std::make_shared<Cache>(
        cacheFactory.set("cache-xml-file", filePath).create());
    return -1;
  } catch (Exception &ex) {
    std::cout << std::endl;
    std::cout << "Exception: msg = " << ex.what() << std::endl;
    LOG(ex.getStackTrace());
  }

  ///////////////testing of invalid_cache3.xml completed///////////////////
  std::cout << "disconnecting..." << std::endl;
  try {
    std::cout << "just before disconnecting..." << std::endl;
    if (cptr != nullptr && !cptr->isClosed()) {
      cptr->close();
      cptr = nullptr;
    }
  } catch (Exception &ex) {
    std::cout << "Exception: msg = " << ex.what() << std::endl;
    LOG(ex.getStackTrace());
    return -1;
  }
  std::cout << "done with test" << std::endl;
  std::cout << "Test successful!" << std::endl;
  return 0;
}

BEGIN_TEST(ValidXmlTestOverFlow)
  {
    int res = testXmlCacheCreationWithOverflow();
    if (res != 0) {
      FAIL("Test Failed.");
    }
  }
END_TEST(ValidXmlTestOverFlow)
