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

#pragma once

#ifndef GEODE_INTEGRATION_TEST_THINCLIENTPDXSERIALIZER_H_
#define GEODE_INTEGRATION_TEST_THINCLIENTPDXSERIALIZER_H_

#include <string>

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

#include "fw_dunit.hpp"
#include "ThinClientHelper.hpp"
#include "Utils.hpp"
#include "testobject/PdxClassV1.hpp"
#include "testobject/PdxClassV2.hpp"
#include "testobject/NonPdxType.hpp"
#include "ThinClientPdxSerializers.hpp"
#include "CacheRegionHelper.hpp"


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

using apache::geode::client::CacheableBoolean;
using apache::geode::client::UserObjectSizer;

using PdxTests::PdxWrapper;
using PdxTests::TestPdxSerializerForV1;

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

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

void stepOne(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);
  createRegionAndAttachPool("DistRegionAck", USE_ACK, poolNames[0],
                            false /*Caching disabled*/);
  LOG("StepOne complete.");
}

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

DUNIT_TASK_DEFINITION(CLIENT1, StepOnePoolLoc_PDX)
  {
    LOG("Starting Step One with Pool + Locator lists");
    stepOne(true);
  }
END_TASK_DEFINITION

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

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

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

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

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

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

DUNIT_TASK_DEFINITION(CLIENT2, StepTwoPoolLoc_PDX)
  {
    LOG("Starting Step Two with Pool + Locator");
    stepOne(true);
  }
END_TASK_DEFINITION

void checkPdxInstanceToStringAtServer(std::shared_ptr<Region> region) {
  auto keyPort = CacheableKey::create("success");
  auto checkPdxInstanceToStringAtServer =
      std::dynamic_pointer_cast<CacheableBoolean>(region->get(keyPort));
  bool actualValue = checkPdxInstanceToStringAtServer->value();
  ASSERT(actualValue == true,
         "checkPdxInstanceToStringAtServer: Val should be true");
}

DUNIT_TASK_DEFINITION(CLIENT1, JavaPutGet)
  {
    CacheRegionHelper::getCacheImpl(cacheHelper->getCache().get())
        ->getTypeRegistry()
        .registerPdxSerializer(std::make_shared<TestPdxSerializer>());

    auto region0 = getHelper()->getRegion("DistRegionAck");
    auto keyPort = CacheableKey::create(1);

    auto nonPdxType1 = std::make_shared<PdxTests::NonPdxType>();
    auto pdxWrapper1 = std::make_shared<PdxWrapper>(nonPdxType1, CLASSNAME1);
    region0->put(keyPort, pdxWrapper1);

    auto pdxWrapper2 =
        std::dynamic_pointer_cast<PdxWrapper>(region0->get(keyPort));

    auto regionGetSuccess =
        std::dynamic_pointer_cast<CacheableBoolean>(region0->get("success"));
    bool actualValue = regionGetSuccess->value();

    ASSERT(actualValue == true,
           "Task JavaPutGet:Objects of type NonPdxType should be equal");

    auto nonPdxType2 = std::static_pointer_cast<PdxTests::NonPdxType>(
        pdxWrapper2->getObject());

    ASSERT(nonPdxType1->equals(*nonPdxType2, false), "NonPdxType compare");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, JavaGet)
  {
    CacheRegionHelper::getCacheImpl(cacheHelper->getCache().get())
        ->getTypeRegistry()
        .registerPdxSerializer(std::make_shared<TestPdxSerializer>());

    LOGDEBUG("JavaGet-1 Line_309");
    auto region0 = getHelper()->getRegion("DistRegionAck");

    auto keyPort1 = CacheableKey::create(1);

    LOGDEBUG("JavaGet-2 Line_314");
    auto pdxWrapper1 =
        std::dynamic_pointer_cast<PdxWrapper>(region0->get(keyPort1));
    auto nonPdxType1 = std::static_pointer_cast<PdxTests::NonPdxType>(
        pdxWrapper1->getObject());

    LOGDEBUG("JavaGet-3 Line_316");
    auto keyPort2 = CacheableKey::create("putFromjava");

    LOGDEBUG("JavaGet-4 Line_316");
    auto pdxWrapper2 =
        std::dynamic_pointer_cast<PdxWrapper>(region0->get(keyPort2));
    auto nonPdxWrapper2 = std::static_pointer_cast<PdxTests::NonPdxType>(
        pdxWrapper2->getObject());

    LOGDEBUG("JavaGet-5 Line_320");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, putFromVersion1_PS)
  {
    auto region0 = getHelper()->getRegion("DistRegionAck");
    auto key = CacheableKey::create(1);

    CacheRegionHelper::getCacheImpl(cacheHelper->getCache().get())
        ->getTypeRegistry()
        .registerPdxSerializer(std::make_shared<TestPdxSerializerForV1>());

    // Create New object and wrap it in PdxWrapper (owner)
    auto nonPdxType1 = std::make_shared<PdxTests::TestDiffTypePdxSV1>(true);
    auto pdxWrapper = std::make_shared<PdxWrapper>(nonPdxType1, V1CLASSNAME2);

    // PUT
    region0->put(key, pdxWrapper);

    // GET
    auto pdxWrapper2 = std::dynamic_pointer_cast<PdxWrapper>(region0->get(key));
    auto nonPdxType2 = std::static_pointer_cast<PdxTests::TestDiffTypePdxSV1>(
        pdxWrapper2->getObject());

    // Equal check
    bool isEqual = nonPdxType1->equals(*nonPdxType2);
    LOGDEBUG("putFromVersion1_PS isEqual = %d", isEqual);
    ASSERT(isEqual == true,
           "Task putFromVersion1_PS:Objects of type TestPdxSerializerForV1 "
           "should be equal");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, putFromVersion2_PS)
  {
    auto region0 = getHelper()->getRegion("DistRegionAck");
    auto key = CacheableKey::create(1);

    CacheRegionHelper::getCacheImpl(cacheHelper->getCache().get())
        ->getTypeRegistry()
        .registerPdxSerializer(
            std::shared_ptr<PdxSerializer>(new TestPdxSerializerForV2));

    // Create New object and wrap it in PdxWrapper (owner)
    auto nonPdxType1 = std::make_shared<PdxTests::TestDiffTypePdxSV2>(true);
    auto pdxWrapper = std::make_shared<PdxWrapper>(nonPdxType1, V2CLASSNAME4);

    // PUT
    region0->put(key, pdxWrapper);

    // GET
    auto pdxWrapper2 = std::dynamic_pointer_cast<PdxWrapper>(region0->get(key));
    auto nonPdxType2 = std::static_pointer_cast<PdxTests::TestDiffTypePdxSV2>(
        pdxWrapper2->getObject());

    // Equal check
    bool isEqual = nonPdxType1->equals(*nonPdxType2);
    LOGDEBUG("putFromVersion2_PS isEqual = %d", isEqual);
    ASSERT(isEqual == true,
           "Task putFromVersion2_PS:Objects of type TestPdxSerializerForV2 "
           "should be equal");

    auto key2 = CacheableKey::create(2);
    region0->put(key2, pdxWrapper);
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, getputFromVersion1_PS)
  {
    auto region0 = getHelper()->getRegion("DistRegionAck");
    auto key = CacheableKey::create(1);

    // GET
    auto pdxWrapper2 = std::dynamic_pointer_cast<PdxWrapper>(region0->get(key));
    auto nonPdxType2 = std::static_pointer_cast<PdxTests::TestDiffTypePdxSV1>(
        pdxWrapper2->getObject());

    // Create New object and Compare
    auto nonPdxType1 = std::make_shared<PdxTests::TestDiffTypePdxSV1>(true);
    bool isEqual = nonPdxType1->equals(*nonPdxType2);
    LOGDEBUG("getputFromVersion1_PS-1 isEqual = %d", isEqual);
    ASSERT(isEqual == true,
           "Task getputFromVersion1_PS:Objects of type TestPdxSerializerForV1 "
           "should be equal");

    // PUT
    region0->put(key, pdxWrapper2);

    auto key2 = CacheableKey::create(2);
    pdxWrapper2 = std::dynamic_pointer_cast<PdxWrapper>(region0->get(key2));
    auto pRet = std::static_pointer_cast<PdxTests::TestDiffTypePdxSV1>(
        pdxWrapper2->getObject());
    isEqual = nonPdxType1->equals(*pRet);
    LOGDEBUG("getputFromVersion1_PS-2 isEqual = %d", isEqual);
    ASSERT(isEqual == true,
           "Task getputFromVersion1_PS:Objects of type TestPdxSerializerForV1 "
           "should be equal");

    // Get then Put.. this should Not merge data back
    auto pdxWrapper = std::make_shared<PdxWrapper>(nonPdxType1, V1CLASSNAME2);
    region0->put(key2, pdxWrapper);
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, getAtVersion2_PS)
  {
    auto region0 = getHelper()->getRegion("DistRegionAck");
    auto key = CacheableKey::create(1);

    // New object
    auto testDiffTpePdxSV2 = new PdxTests::TestDiffTypePdxSV2(true);

    // GET
    auto pdxWrapper2 = std::dynamic_pointer_cast<PdxWrapper>(region0->get(key));
    auto pRet = std::static_pointer_cast<PdxTests::TestDiffTypePdxSV2>(
        pdxWrapper2->getObject());

    bool isEqual = testDiffTpePdxSV2->equals(*pRet);
    LOGDEBUG("getAtVersion2_PS-1 isEqual = %d", isEqual);
    ASSERT(
        isEqual == true,
        "Task getAtVersion2_PS:Objects of type TestPdxSerializerForV2 should "
        "be equal");

    auto key2 = CacheableKey::create(2);
    testDiffTpePdxSV2 = new PdxTests::TestDiffTypePdxSV2(true);

    pdxWrapper2 = std::dynamic_pointer_cast<PdxWrapper>(region0->get(key2));
    pRet = std::static_pointer_cast<PdxTests::TestDiffTypePdxSV2>(
        pdxWrapper2->getObject());
    isEqual = testDiffTpePdxSV2->equals(*pRet);

    LOGDEBUG("getAtVersion2_PS-2 isEqual = %d", isEqual);
    ASSERT(
        isEqual == false,
        "Task getAtVersion2_PS:Objects of type TestPdxSerializerForV2 should "
        "be equal");
  }
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

#endif  // GEODE_INTEGRATION_TEST_THINCLIENTPDXSERIALIZER_H_
