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

using namespace apache::geode::client;
using namespace test;
using namespace testData;
using namespace PdxTests;

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

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->addPdxType(PdxTypes1::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(PdxTypes2::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(PdxTypes3::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(PdxTypes4::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(PdxTypes5::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(PdxTypes6::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(PdxTypes7::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(PdxTypes8::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(PdxTypes9::createDeserializable);
	}
	catch (const IllegalStateException&) {
		// ignore exception
	}
	try {
		serializationRegistry->addPdxType(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