/*
 * 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_THINCLIENTDISTOPS2_H_
#define GEODE_INTEGRATION_TEST_THINCLIENTDISTOPS2_H_

#include "fw_dunit.hpp"
#include <ace/OS.h>

#include <string>
#include <vector>

#define ROOT_NAME "ThinClientDistOps2"
#define ROOT_SCOPE DISTRIBUTED_ACK

#include "ThinClientHelper.hpp"

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

namespace { // NOLINT(google-build-namespaces)

using apache::geode::client::CacheableInt32;
using apache::geode::client::CacheableInt64;
using apache::geode::client::CacheableKey;
using apache::geode::client::CacheableString;
using apache::geode::client::CacheHelper;
using apache::geode::client::CacheServerException;
using apache::geode::client::EntryExistsException;
using apache::geode::client::IllegalArgumentException;
using apache::geode::client::Properties;

static bool isLocalServer = false;
static bool isLocator = false;
static int numberOfLocators = 0;
const char* poolName = "__TEST_POOL1__";

const char* locatorsG =
    CacheHelper::getLocatorHostPort(isLocator, isLocalServer, numberOfLocators);

#include "LocatorHelper.hpp"

#define verifyEntry(a, b, c, d) _verifyEntry(a, b, c, d, __LINE__)

void _verifyEntry(const std::string& name, const char* key, const char* val,
                  bool checkLocal, int line) {
  char logmsg[1024];
  sprintf(logmsg, "verifyEntry() called from %d.\n", line);
  LOG(logmsg);
  _verifyEntry(name, key, val, false, checkLocal);
  LOG("Entry verified.");
}

const char* _keys[] = {"Key-1", "Key-2", "Key-3", "Key-4"};
const char* _vals[] = {"Value-1", "Value-2", "Value-3", "Value-4"};
const char* _nvals[] = {"New Value-1", "New Value-2", "New Value-3",
                        "New Value-4"};

const char* _regionNames[] = {"DistRegionAck", "DistRegionNoAck"};

DUNIT_TASK_DEFINITION(SERVER1, CreateServer1)
  {
    if (isLocalServer) CacheHelper::initServer(1);
    LOG("SERVER1 started");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(SERVER2, CreateServer2And3)
  {
    if (isLocalServer) CacheHelper::initServer(2);
    if (isLocalServer) CacheHelper::initServer(3);
    LOG("SERVER23 started");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(SERVER2, CreateServer2And3_Locator)
  {
    if (isLocalServer) CacheHelper::initServer(2, nullptr, locatorsG);
    if (isLocalServer) CacheHelper::initServer(3, nullptr, locatorsG);
    LOG("SERVER23 started");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, CreateClient1Regions_Pooled_Locator)
  {
    initClientWithPool(true, "__TEST_POOL1__", locatorsG, nullptr, nullptr, 0,
                       true);
    createPooledRegion(_regionNames[0], USE_ACK, locatorsG, poolName);
    createPooledRegion(_regionNames[1], NO_ACK, locatorsG, poolName);
    LOG("CreateClient1Regions complete.");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, CreateClient2Regions_Pooled_Locator)
  {
    initClientWithPool(true, "__TEST_POOL1__", locatorsG, nullptr, nullptr, 0,
                       true);
    createPooledRegion(_regionNames[0], USE_ACK, locatorsG, poolName);
    createPooledRegion(_regionNames[1], NO_ACK, locatorsG, poolName);
    LOG("CreateClient1Regions complete.");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, CreateClient1Entries)
  {
    createEntry(_regionNames[0], _keys[0], _vals[0]);
    createEntry(_regionNames[1], _keys[2], _vals[2]);
    LOG("CreateClient1Entries complete.");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, CreateClient2Entries)
  {
    doNetsearch(_regionNames[0], _keys[0], _vals[0]);
    doNetsearch(_regionNames[1], _keys[2], _vals[2]);
    createEntry(_regionNames[0], _keys[1], _vals[1]);
    createEntry(_regionNames[1], _keys[3], _vals[3]);
    LOG("CreateClient2Entries complete.");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, UpdateClient1Entry)
  {
    doNetsearch(_regionNames[0], _keys[1], _vals[1]);
    doNetsearch(_regionNames[1], _keys[3], _vals[3]);
    updateEntry(_regionNames[0], _keys[0], _nvals[0]);
    updateEntry(_regionNames[1], _keys[2], _nvals[2]);
    LOG("UpdateClient1Entry complete.");
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, UpdateClient2Entry)
  {
    doNetsearch(_regionNames[0], _keys[0], _vals[0], false);
    doNetsearch(_regionNames[1], _keys[2], _vals[2], false);
    updateEntry(_regionNames[0], _keys[1], _nvals[1]);
    updateEntry(_regionNames[1], _keys[3], _nvals[3]);
    LOG("UpdateClient2Entry complete.");
  }
END_TASK_DEFINITION

// Test for getAll
DUNIT_TASK_DEFINITION(CLIENT1, Client1GetAll)
  {
    auto reg0 = getHelper()->getRegion(_regionNames[0]);

    std::vector<std::shared_ptr<CacheableKey>> keys0;
    auto key0 = CacheableString::create(_keys[0]);
    auto key1 = CacheableString::create(_keys[1]);

    // re-create region with caching enabled
    reg0->localDestroyRegion();
    reg0 = nullptr;
    getHelper()->createPooledRegion(regionNames[0], USE_ACK, nullptr,
                                    "__TEST_POOL1__", true, true);
    reg0 = getHelper()->getRegion(_regionNames[0]);
    // check for IllegalArgumentException for empty key list
    keys0.clear();
    try {
      reg0->getAll(keys0);
      FAIL("Expected IllegalArgumentException");
    } catch (const IllegalArgumentException&) {
      LOG("Got expected IllegalArgumentException");
    }

    keys0.push_back(key0);
    keys0.push_back(key1);
    {
      auto values = reg0->getAll(keys0);
      ASSERT(values.size() == 2, "Expected 2 values");
      auto val0 = std::dynamic_pointer_cast<CacheableString>(values[key0]);
      auto val1 = std::dynamic_pointer_cast<CacheableString>(values[key1]);
      ASSERT(strcmp(_nvals[0], val0->value().c_str()) == 0,
             "Got unexpected value");
      ASSERT(strcmp(_nvals[1], val1->value().c_str()) == 0,
             "Got unexpected value");
    }

    // for second region invalidate only one key to have a partial get
    // from java server
    auto reg1 = getHelper()->getRegion(_regionNames[1]);
    auto key2 = CacheableString::create(_keys[2]);
    auto key3 = CacheableString::create(_keys[3]);
    reg1->localInvalidate(key2);
    std::vector<std::shared_ptr<CacheableKey>> keys1;
    keys1.push_back(key2);
    keys1.push_back(key3);

    {
      auto values = reg1->getAll(keys1);
      ASSERT(values.size() == 2, "Expected 2 values");
      auto val2 = std::dynamic_pointer_cast<CacheableString>(values[key2]);
      auto val3 = std::dynamic_pointer_cast<CacheableString>(values[key3]);
      ASSERT(strcmp(_nvals[2], val2->value().c_str()) == 0,
             "Got unexpected value");
      ASSERT(strcmp(_vals[3], val3->value().c_str()) == 0,
             "Got unexpected value");
    }

    // also check that the region is properly populated
    ASSERT(reg1->size() == 2, "Expected 2 entries in the region");
    auto regEntries = reg1->entries(false);
    ASSERT(regEntries.size() == 2, "Expected 2 entries in the region.entries");
    verifyEntry(_regionNames[1], _keys[2], _nvals[2], true);
    verifyEntry(_regionNames[1], _keys[3], _vals[3], true);

    // also check with nullptr values that region is properly populated
    {
      reg1->localInvalidate(key3);
      auto values = reg1->getAll(keys1);
      // now check that the region is properly populated
      ASSERT(reg1->size() == 2, "Expected 2 entries in the region");
      regEntries = reg1->entries(false);
      ASSERT(regEntries.size() == 2,
             "Expected 2 entries in the region.entries");
      verifyEntry(_regionNames[1], _keys[2], _nvals[2], true);
      verifyEntry(_regionNames[1], _keys[3], _nvals[3], true);
    }
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, Client1GetAll_Pool)
  {
    {
      auto reg0 = getHelper()->getRegion(_regionNames[0]);

      std::vector<std::shared_ptr<CacheableKey>> keys0;
      auto key0 = CacheableString::create(_keys[0]);
      auto key1 = CacheableString::create(_keys[1]);

      getHelper()->createRegionAndAttachPool(_regionNames[0], USE_ACK,
                                             poolName);
      reg0 = getHelper()->getRegion(_regionNames[0]);
      // check for IllegalArgumentException for empty key list
      keys0.clear();
      try {
        reg0->getAll(keys0);
        FAIL("Expected IllegalArgumentException");
      } catch (const IllegalArgumentException&) {
        LOG("Got expected IllegalArgumentException");
      }

      keys0.push_back(key0);
      keys0.push_back(key1);

      auto values = reg0->getAll(keys0);

      ASSERT(values.size() == 2, "Expected 2 values");
      auto val0 = std::dynamic_pointer_cast<CacheableString>(values[key0]);
      auto val1 = std::dynamic_pointer_cast<CacheableString>(values[key1]);
      ASSERT(strcmp(_nvals[0], val0->value().c_str()) == 0,
             "Got unexpected value");
      ASSERT(strcmp(_nvals[1], val1->value().c_str()) == 0,
             "Got unexpected value");
    }

    {
      // for second region invalidate only one key to have a partial get
      // from java server
      auto reg1 = getHelper()->getRegion(_regionNames[1]);
      auto key2 = CacheableString::create(_keys[2]);
      auto key3 = CacheableString::create(_keys[3]);
      reg1->localInvalidate(key2);
      std::vector<std::shared_ptr<CacheableKey>> keys1;
      keys1.push_back(key2);
      keys1.push_back(key3);

      auto values = reg1->getAll(keys1);

      ASSERT(values.size() == 2, "Expected 2 values");
      auto val2 = std::dynamic_pointer_cast<CacheableString>(values[key2]);
      auto val3 = std::dynamic_pointer_cast<CacheableString>(values[key3]);
      ASSERT(strcmp(_nvals[2], val2->value().c_str()) == 0,
             "Got unexpected value");
      ASSERT(strcmp(_vals[3], val3->value().c_str()) == 0,
             "Got unexpected value");

      // also check that the region is properly populated
      ASSERT(reg1->size() == 2, "Expected 2 entries in the region");
      auto regEntries = reg1->entries(false);
      ASSERT(regEntries.size() == 2,
             "Expected 2 entries in the region.entries");
      verifyEntry(_regionNames[1], _keys[2], _nvals[2], true);
      verifyEntry(_regionNames[1], _keys[3], _vals[3], true);

      // also check with nullptr values that region is properly populated
      reg1->localInvalidate(key3);

      reg1->getAll(keys1);
      // now check that the region is properly populated
      ASSERT(reg1->size() == 2, "Expected 2 entries in the region");
      regEntries = reg1->entries(false);
      ASSERT(regEntries.size() == 2,
             "Expected 2 entries in the region.entries");
      verifyEntry(_regionNames[1], _keys[2], _nvals[2], true);
      verifyEntry(_regionNames[1], _keys[3], _nvals[3], true);
    }
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, CloseCache1)
  { cleanProc(); }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, CloseCache2)
  { cleanProc(); }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(SERVER1, CloseServer1)
  {
    if (isLocalServer) {
      CacheHelper::closeServer(1);
      LOG("SERVER1 stopped");
    }
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(SERVER2, CloseServer2)
  {
    if (isLocalServer) {
      CacheHelper::closeServer(2);
      LOG("SERVER2 stopped");
    }
    if (isLocalServer) {
      CacheHelper::closeServer(3);
      LOG("SERVER3 stopped");
    }
  }
END_TASK_DEFINITION

}  // namespace

#endif  // GEODE_INTEGRATION_TEST_THINCLIENTDISTOPS2_H_
