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

#include "fw_dunit.hpp"

#include <ace/OS.h>
#include <ace/High_Res_Timer.h>

#include <geode/PdxInstance.hpp>
#include <geode/UserFunctionExecutionException.hpp>
#include <geode/FunctionService.hpp>

#define ROOT_NAME "testThinClientPdxTests"
#define ROOT_SCOPE DISTRIBUTED_ACK

#include "ThinClientHelper.hpp"
#include "testobject/PdxClassV1.hpp"
#include "testobject/PdxClassV2.hpp"
#include "testobject/VariousPdxTypes.hpp"
#include "testobject/InvalidPdxUsage.hpp"
#include "QueryStrings.hpp"
#include "QueryHelper.hpp"
#include "Utils.hpp"
#include <geode/Query.hpp>
#include <geode/QueryService.hpp>
#include "CachePerfStats.hpp"
#include <LocalRegion.hpp>

#define CLIENT1 s1p1
#define CLIENT2 s1p2
#define LOCATOR s2p2
#define SERVER1 s2p1

using apache::geode::client::CacheableBoolean;
using apache::geode::client::CacheableVector;
using apache::geode::client::ClassCastException;
using apache::geode::client::FunctionService;
using apache::geode::client::IllegalStateException;
using apache::geode::client::UserFunctionExecutionException;

using PdxTests::PdxTypes1;
using PdxTests::PdxTypes10;
using PdxTests::PdxTypes2;
using PdxTests::PdxTypes3;
using PdxTests::PdxTypes4;
using PdxTests::PdxTypes5;
using PdxTests::PdxTypes6;
using PdxTests::PdxTypes7;
using PdxTests::PdxTypes8;
using PdxTests::PdxTypes9;

bool isLocator = false;
bool isLocalServer = false;

const char *poolNames[] = {"Pool1", "Pool2", "Pool3"};
const char *locHostPort =
    CacheHelper::getLocatorHostPort(isLocator, isLocalServer, 1);
bool isPoolConfig = false;  // To track if pool case is running
// const char * qRegionNames[] = { "Portfolios", "Positions", "Portfolios2",
// "Portfolios3" };

void initClient(const bool isthinClient, bool isPdxIgnoreUnreadFields,
                const std::shared_ptr<Properties> &configPtr = nullptr) {
  LOGINFO("isPdxIgnoreUnreadFields = %d ", isPdxIgnoreUnreadFields);
  if (cacheHelper == nullptr) {
    cacheHelper = new CacheHelper(isthinClient, isPdxIgnoreUnreadFields, false,
                                  configPtr, false);
  }
  ASSERT(cacheHelper, "Failed to create a CacheHelper client instance.");
}

void initClient1(bool isPdxIgnoreUnreadFields = false) {
  // Create just one pool and attach all regions to that.
  initClient(true, isPdxIgnoreUnreadFields);
  isPoolConfig = true;
  createPool(poolNames[0], locHostPort, nullptr, 0, false);
  createRegionAndAttachPool("DistRegionAck", USE_ACK, poolNames[0],
                            true /*Caching enabled*/);
  LOG("StepOne complete.");
}

void initClient2(bool isPdxIgnoreUnreadFields = false) {
  // Create just one pool and attach all regions to that.
  initClient(true, isPdxIgnoreUnreadFields);
  isPoolConfig = true;
  createPool(poolNames[0], locHostPort, nullptr, 0,
             true /*ClientNotification enabled*/);
  createRegionAndAttachPool("DistRegionAck", USE_ACK, poolNames[0],
                            true /*Caching enabled*/);
  LOG("StepOne complete.");
}

DUNIT_TASK_DEFINITION(SERVER1, StartLocator)
  {
    // starting locator 1 2
    if (isLocator) {
      CacheHelper::initLocator(1);
    }
    LOG("Locator started");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(SERVER1, CreateServerWithLocator_PdxMetadataTest)
  {
    LOG("Starting SERVER1...");
    if (isLocalServer) {
      CacheHelper::initServer(1, "cacheserverPdx2.xml", locHostPort);
    }
    LOG("SERVER1 started");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, StepOnePoolLoc_PdxMetadataTest)
  {
    LOG("Starting Step One with Pool + Locator lists");
    initClient1();
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, StepTwoPoolLoc_PdxMetadataTest)
  {
    LOG("Starting Step Two with Pool + Locator");
    initClient2();
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, generateJavaPdxType)
  {
    auto regPtr0 = getHelper()->getRegion("DistRegionAck");
    auto args = CacheableKey::create("saveAllJavaPdxTypes");
    auto key = CacheableKey::create(1);
    auto routingObj = CacheableVector::create();
    routingObj->push_back(key);

    auto funcExec = FunctionService::onRegion(regPtr0);

    auto collector = funcExec.withArgs(args)
                         .withFilter(routingObj)
                         .execute("ComparePdxTypes");
    ASSERT(collector != nullptr, "onRegion collector nullptr");

    auto result = collector->getResult();
    LOGINFO("NIL:: testTCPDXTests: result->size = %d ", result->size());
    if (result == nullptr) {
      ASSERT(false, "echo String : result is nullptr");
    } else {
      //
      bool gotResult = false;
      for (size_t i = 0; i < result->size(); i++) {
        try {
          auto boolValue = std::dynamic_pointer_cast<CacheableBoolean>(
              result->operator[](i));
          LOGINFO("NIL:: boolValue is %d ", boolValue->value());
          bool resultVal = boolValue->value();
          ASSERT(resultVal == true,
                 "Function should return true NIL LINE_1508");
          gotResult = true;
        } catch (ClassCastException &ex) {
          LOG("exFuncNameSendException casting to int for arrayList arguement "
              "exception.");
          std::string logmsg = "";
          logmsg += ex.getName();
          logmsg += ": ";
          logmsg += ex.what();
          LOG(logmsg.c_str());
          LOG(ex.getStackTrace());
          LOG("exFuncNameSendException now casting to "
              "UserFunctionExecutionExceptionPtr for arrayList arguement "
              "exception.");
          auto uFEPtr =
              std::dynamic_pointer_cast<UserFunctionExecutionException>(
                  result->operator[](i));
          ASSERT(uFEPtr != nullptr, "uFEPtr exception is nullptr");
          LOGINFO("Done casting to uFEPtr");
          LOGINFO("Read expected uFEPtr exception %s ",
                  uFEPtr->getMessage().c_str());
        } catch (...) {
          FAIL(
              "exFuncNameSendException casting to string for bool arguement "
              "Unknown exception.");
        }
      }
      ASSERT(gotResult == true, "Function should (gotResult) return true ");
      //
    }
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, putAllPdxTypes)
  {
    auto serializationRegistry =
        CacheRegionHelper::getCacheImpl(cacheHelper->getCache().get())
            ->getSerializationRegistry();

    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes1::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes2::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes3::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes4::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes5::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes6::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes7::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes8::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes9::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    try {
      serializationRegistry->addPdxSerializableType(
          PdxTypes10::createDeserializable);
    } catch (const IllegalStateException &) {
      // ignore exception
    }
    // TODO::Uncomment it once PortfolioPdx/PositionPdx Classes are ready
    // serializationRegistry->addPdxType(PdxTests.PortfolioPdx.CreateDeserializable);
    // serializationRegistry->addPdxType(PdxTests.PositionPdx.CreateDeserializable);

    auto regPtr0 = getHelper()->getRegion("DistRegionAck");

    auto p1 = std::make_shared<PdxTypes1>();
    auto keyport1 = CacheableKey::create(p1->getClassName().c_str());
    regPtr0->put(keyport1, p1);

    auto p2 = std::make_shared<PdxTypes2>();
    auto keyport2 = CacheableKey::create(p2->getClassName().c_str());
    regPtr0->put(keyport2, p2);

    auto p3 = std::make_shared<PdxTypes3>();
    auto keyport3 = CacheableKey::create(p3->getClassName().c_str());
    regPtr0->put(keyport3, p3);

    auto p4 = std::make_shared<PdxTypes4>();
    auto keyport4 = CacheableKey::create(p4->getClassName().c_str());
    regPtr0->put(keyport4, p4);

    auto p5 = std::make_shared<PdxTypes5>();
    auto keyport5 = CacheableKey::create(p5->getClassName().c_str());
    regPtr0->put(keyport5, p5);

    auto p6 = std::make_shared<PdxTypes6>();
    auto keyport6 = CacheableKey::create(p6->getClassName().c_str());
    regPtr0->put(keyport6, p6);

    auto p7 = std::make_shared<PdxTypes7>();
    auto keyport7 = CacheableKey::create(p7->getClassName().c_str());
    regPtr0->put(keyport7, p7);

    auto p8 = std::make_shared<PdxTypes8>();
    auto keyport8 = CacheableKey::create(p8->getClassName().c_str());
    regPtr0->put(keyport8, p8);

    auto p9 = std::make_shared<PdxTypes9>();
    auto keyport9 = CacheableKey::create(p9->getClassName().c_str());
    regPtr0->put(keyport9, p9);

    auto p10 = std::make_shared<PdxTypes10>();
    auto keyport10 = CacheableKey::create(p10->getClassName().c_str());
    regPtr0->put(keyport10, p10);

    //
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, verifyDotNetPdxTypes)
  {
    auto regPtr0 = getHelper()->getRegion("DistRegionAck");
    auto args = CacheableKey::create("compareDotNETPdxTypes");
    auto key = CacheableKey::create(1);
    auto routingObj = CacheableVector::create();
    routingObj->push_back(key);

    auto funcExec = FunctionService::onRegion(regPtr0);

    auto collector = funcExec.withArgs(args)
                         .withFilter(routingObj)
                         .execute("ComparePdxTypes");
    ASSERT(collector != nullptr, "onRegion collector nullptr");

    auto result = collector->getResult();
    LOGINFO("NIL:: testTCPDXTests:verifyDotNetPdxTypes result->size = %d ",
            result->size());
    if (result == nullptr) {
      ASSERT(false, "echo String : result is nullptr");
    } else {
      bool gotResult = false;
      for (size_t i = 0; i < result->size(); i++) {
        try {
          auto boolValue = std::dynamic_pointer_cast<CacheableBoolean>(
              result->operator[](i));
          LOGINFO("NIL::verifyDotNetPdxTypes boolValue is %d ",
                  boolValue->value());
          bool resultVal = boolValue->value();
          ASSERT(resultVal == true,
                 "Function should return true NIL LINE_1508");
          gotResult = true;
        } catch (ClassCastException &ex) {
          LOG("exFuncNameSendException casting to int for arrayList arguement "
              "exception.");
          std::string logmsg = "";
          logmsg += ex.getName();
          logmsg += ": ";
          logmsg += ex.what();
          LOG(logmsg.c_str());
          LOG(ex.getStackTrace());
          LOG("exFuncNameSendException now casting to "
              "UserFunctionExecutionExceptionPtr for arrayList arguement "
              "exception.");
          auto uFEPtr =
              std::dynamic_pointer_cast<UserFunctionExecutionException>(
                  result->operator[](i));
          ASSERT(uFEPtr != nullptr, "uFEPtr exception is nullptr");
          LOGINFO("Done casting to uFEPtr");
          LOGINFO("Read expected uFEPtr exception %s ",
                  uFEPtr->getMessage().c_str());
        } catch (...) {
          FAIL(
              "exFuncNameSendException casting to string for bool arguement "
              "Unknown exception.");
        }
      }
      ASSERT(gotResult == true, "Function should (gotResult) return true ");
    }
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, CloseCache1)
  {
    LOG("cleanProc 1...");
    isPoolConfig = false;
    cleanProc();
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, CloseCache2)
  {
    LOG("cleanProc 2...");
    isPoolConfig = false;
    cleanProc();
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(SERVER1, CloseServer)
  {
    LOG("closing Server1...");
    if (isLocalServer) {
      CacheHelper::closeServer(1);
      LOG("SERVER1 stopped");
    }
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(LOCATOR, CloseLocator)
  {
    if (isLocator) {
      CacheHelper::closeLocator(1);
      LOG("Locator1 stopped");
    }
  }
END_TASK_DEFINITION

DUNIT_MAIN
  {
    CALL_TASK(StartLocator);
    CALL_TASK(CreateServerWithLocator_PdxMetadataTest);
    CALL_TASK(StepOnePoolLoc_PdxMetadataTest);
    CALL_TASK(StepTwoPoolLoc_PdxMetadataTest);

    CALL_TASK(generateJavaPdxType);

    CALL_TASK(putAllPdxTypes);

    CALL_TASK(verifyDotNetPdxTypes);

    CALL_TASK(CloseCache1);
    CALL_TASK(CloseCache2);
    CALL_TASK(CloseServer);

    CALL_TASK(CloseLocator);
  }
END_MAIN
