/*
 * 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_THINCLIENTCALLBACKARG_H_
#define GEODE_INTEGRATION_TEST_THINCLIENTCALLBACKARG_H_

#include "fw_dunit.hpp"
#include "ThinClientHelper.hpp"
#include "TallyListener.hpp"
#include "TallyWriter.hpp"

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

/*
 * start server with NBS true
 * start one client which will entry operations ( put/invalidate/destroy ).
 * start 2nd client with cache listener,  writer and client notification true.
 * verify that listener is invoked and writer is not being invoked in 2nd client
 * + callback Argument
 */

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

using apache::geode::client::testing::TallyListener;
using apache::geode::client::testing::TallyWriter;

static bool isLocalServer = false;
static bool isLocator = false;
static int numberOfLocators = 0;
const char* locatorsG =
    CacheHelper::getLocatorHostPort(isLocator, isLocalServer, numberOfLocators);
const char* poolName = "__TESTPOOL1_";
std::shared_ptr<TallyListener> regListener;
std::shared_ptr<TallyWriter> regWriter;

#include "LocatorHelper.hpp"

void setCacheListener(const char* regName,
                      std::shared_ptr<TallyListener> regListener) {
  auto reg = getHelper()->getRegion(regName);
  auto attrMutator = reg->getAttributesMutator();
  attrMutator->setCacheListener(regListener);
}

void setCacheWriter(const char* regName,
                    std::shared_ptr<TallyWriter> regWriter) {
  auto reg = getHelper()->getRegion(regName);
  auto attrMutator = reg->getAttributesMutator();
  attrMutator->setCacheWriter(regWriter);
}

void createClientPooledLocatorRegion() {
  initClient(true);
  auto key0 = CacheableKey::create(keys[0]);
  LOG("Creating region in CLIENT , no-ack, cacheing enable, with-listener and "
      "writer");
  createPooledRegion(regionNames[0], false, locatorsG, poolName, true,
                     regListener, true);
  regWriter = std::make_shared<TallyWriter>();
  setCacheWriter(regionNames[0], regWriter);
  regListener = std::make_shared<TallyListener>();
  setCacheListener(regionNames[0], regListener);
  regWriter->setCallBackArg(key0);
  regListener->setCallBackArg(key0);
  auto regPtr0 = getHelper()->getRegion(regionNames[0]);
  regPtr0->registerAllKeys();
}
void validateLocalListenerWriterData() {
  SLEEP(2000);
  ASSERT(regWriter->isWriterInvoked() == true, "Writer Should be invoked");
  ASSERT(regListener->isListenerInvoked() == true,
         "Listener Should be invoked");
  ASSERT(regWriter->isCallBackArgCalled() == true,
         "Writer CallbackArg Should be invoked");
  ASSERT(regListener->isCallBackArgCalled() == true,
         "Listener CallbackArg Should be invoked");
  regListener->showTallies();
  regWriter->showTallies();
}

void validateRemoteListenerWriterData() {
  SLEEP(2000);
  ASSERT(regWriter->isWriterInvoked() == false, "Writer Should not be invoked");
  ASSERT(regListener->isListenerInvoked() == true,
         "Listener Should be invoked");
  ASSERT(regWriter->isCallBackArgCalled() == false,
         "Writer CallbackArg Should not be invoked");
  ASSERT(regListener->isCallBackArgCalled() == true,
         "Listener CallbackArg Should be invoked");
  regListener->showTallies();
}

DUNIT_TASK_DEFINITION(CLIENT1, SetupClient1_Pooled_Locator)
  { createClientPooledLocatorRegion(); }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT2, SetupClient2_Pooled_Locator)
  { createClientPooledLocatorRegion(); }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, doOperations)
  {
    auto key0 = CacheableKey::create(keys[0]);
    LOG("do entry operation from client 1");
    RegionOperations region(regionNames[0]);
    region.putOp(5, key0);
    SLEEP(1000);  // let the events reach at other end.
    region.putOp(5, key0);
    SLEEP(1000);
    region.invalidateOp(5, key0);
    SLEEP(1000);
    region.destroyOp(5, key0);
    SLEEP(1000);
    region.putOp(5, key0);
    SLEEP(1000);  // let the events reach at other end.
    region.removeOp(5, key0);
    SLEEP(1000);
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, validateLocalListenerWriter)
  {
    validateLocalListenerWriterData();
    ASSERT(regWriter->getCreates() == 10, "Should be 5 creates");
    ASSERT(regListener->getCreates() == 10, "Should be 5 creates");
    ASSERT(regListener->getUpdates() == 5, "Should be 5 updates");
    ASSERT(regWriter->getUpdates() == 5, "Should be 5 updates");
    ASSERT(regListener->getInvalidates() == 5, "Should be 5 Invalidate");
    ASSERT(regWriter->getInvalidates() == 0, "Should be 0 Invalidate");
    ASSERT(regListener->getDestroys() == 10,
           "Should be 5 destroy");  // 5 destroys + 5 removes
    ASSERT(regWriter->getDestroys() == 10,
           "Should be 5 destroy");  // 5 destroys + 5 removes
  }
END_TASK_DEFINITION

/*
 * Remote side listener callback argument not found. it seemd server doesnt send
 * callback argument.
 * will check later.
 */
/*
DUNIT_TASK_DEFINITION(CLIENT2, validateRemoteListenerWriter)
{
  validateRemoteListenerWriterData();
  ASSERT( regListener->getCreates() == 5, "Should be 5 creates" );
  ASSERT( regListener->getUpdates() == 5, "Should be 5 updates" );
  ASSERT( regListener->getInvalidates() == 0, "Should be 0 Invalidate" );
  ASSERT( regListener->getDestroys() == 5, "Should be 5 destroy" );
}
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
void runCallbackArg() {
  CALL_TASK(CreateLocator1);
  CALL_TASK(CreateServer1_With_Locator);

  CALL_TASK(SetupClient1_Pooled_Locator);
  CALL_TASK(SetupClient2_Pooled_Locator);

  CALL_TASK(doOperations);
  CALL_TASK(validateLocalListenerWriter);
  // CALL_TASK(validateRemoteListenerWriter);
  CALL_TASK(CloseCache1);
  CALL_TASK(CloseCache2);
  CALL_TASK(CloseServer1);

  CALL_TASK(CloseLocator1);
}

}  // namespace

#endif  // GEODE_INTEGRATION_TEST_THINCLIENTCALLBACKARG_H_
