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

#define ROOT_NAME "testThinClientTracking"

#include "ThinClientSecurityHelper.hpp"

#define SERVER s1p1
#define CLIENT1 s1p2
#define CLIENT2 s2p1

// This is the test for tracking work.

putThread *thread1 = nullptr;
putThread *thread2 = nullptr;

void createAuthzRegion() {
  initCredentialGenerator();
  initClientAuth('A');
  std::shared_ptr<Region> rptr;
  createRegion(regionNamesAuth[0], false, true);
  rptr = getHelper()->getRegion(regionNamesAuth[0]);
  rptr->registerAllKeys();
}
void verifyEntry(const char *value) {
  auto rptr = getHelper()->getRegion(regionNamesAuth[0]);
  auto entry = rptr->getEntry("key-1");
  ASSERT(entry != nullptr, "Key should have been found in region.");
  auto valuePtr = std::dynamic_pointer_cast<CacheableString>(entry->getValue());
  char buf1[1024];

  if (valuePtr == nullptr) {
    FAIL("Value was null.");
  }
  sprintf(buf1, "value for key-1 is %s", valuePtr->value().c_str());
  LOG(buf1);
  ASSERT(strcmp(valuePtr->value().c_str(), value) == 0,
         "Updated value not found in region.");
}
DUNIT_TASK_DEFINITION(SERVER, StartServer1)
  {
    initCredentialGenerator();
    std::string cmdServerAuthenticator;

    if (isLocalServer) {
      cmdServerAuthenticator = credentialGeneratorHandler->getServerCmdParams(
          "authenticator:dummy", getXmlPath());
      printf("string %s", cmdServerAuthenticator.c_str());
      CacheHelper::initServer(
          1, "cacheserver_notify_subscription.xml", locHostPort,
          const_cast<char *>(cmdServerAuthenticator.c_str()));
      LOG("Server1 started");
    }
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(SERVER, StartLocator)
  {
    if (isLocator) {
      CacheHelper::initLocator(1);
      LOG("Locator1 started");
    }
  }
END_TASK_DEFINITION

DUNIT_TASK_DEFINITION(CLIENT1, StartClient1)
  {
    createAuthzRegion();
    LOG("CLIENT1 started");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT2, StartClient2)
  {
    createAuthzRegion();
    LOG("CLIENT2 started");
  }
END_TASK_DEFINITION
// check that tracking work correctly with put.
DUNIT_TASK_DEFINITION(CLIENT1, PutOnClient1)
  {
    auto rptr = getHelper()->getRegion(regionNamesAuth[0]);
    thread1 = new putThread(rptr);
    thread1->setParams(0, 1, 1, true);
    thread1->start();
    LOG("PutOnClient1 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT2, PutOnClient2)
  {
    auto rptr = getHelper()->getRegion(regionNamesAuth[0]);
    thread2 = new putThread(rptr);
    thread2->setParams(0, 1, 1);
    thread2->start();
    thread2->stop();
    delete thread2;
    LOG("PutOnClient2 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT1, VerifyOnClient1)
  {
    verifyEntry("client2-value1");
    LOG("VerifyOnClient1 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT2, VerifyOnClient2)
  {
    SLEEP(5000);
    verifyEntry("client2-value1");
    LOG("VerifyOnClient2 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT1, VerifyOnClient12)
  {
    thread1->stop();
    delete thread1;
    verifyEntry("client2-value1");

    LOG("VerifyOnClient12 completed");
  }
END_TASK_DEFINITION
// check that tracking work correctly with destroy.
DUNIT_TASK_DEFINITION(CLIENT1, DestroyOnClient1)
  {
    auto rptr = getHelper()->getRegion(regionNamesAuth[0]);
    thread1 = new putThread(rptr);
    thread1->setParams(0, 1, 1, true);
    thread1->start();
    LOG("DestroyOnClient1 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT2, DestroyOnClient2)
  {
    auto rptr = getHelper()->getRegion(regionNamesAuth[0]);
    thread2 = new putThread(rptr);
    thread2->setParams(2, 1, 1);
    thread2->start();
    thread2->stop();
    delete thread2;
    LOG("DestroyOnClient2 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT1, VerifyDestroyOnClient1)
  {
    verifyDestroyed(regionNamesAuth[0], "key-1");
    LOG("VerifyDestroyOnClient1 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT2, VerifyDestroyOnClient2)
  {
    SLEEP(5000);
    verifyDestroyed(regionNamesAuth[0], "key-1");
    LOG("VerifyDestroyOnClient2 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT1, VerifyDestroyOnClient12)
  {
    thread1->stop();
    delete thread1;
    verifyDestroyed(regionNamesAuth[0], "key-1");
    LOG("VerifyDestroyOnClient12 completed");
  }
END_TASK_DEFINITION
// check that Conversion from Tracked Map Entry and back work correctly
DUNIT_TASK_DEFINITION(CLIENT1, PutTrackedMapOnClient1)
  {
    auto rptr = getHelper()->getRegion(regionNamesAuth[0]);
    thread1 = new putThread(rptr);
    thread1->setParams(0, 1, 1, true);
    thread1->start();
    LOG("PutTrackedMapOnClient1 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT2, PutTrackedMapOnClient2)
  {
    auto rptr = getHelper()->getRegion(regionNamesAuth[0]);
    thread2 = new putThread(rptr);
    thread2->setParams(0, 10, 1, false, true);
    thread2->start();
    thread2->stop();
    delete thread2;
    verifyEntry("client2-value10");
    LOG("PutTrackedMapOnClient2 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT1, VerifyTrackedMapOnClient1)
  {
    verifyEntry("client2-value10");
    LOG("VerifyTrackedMapOnClient1 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT2, VerifyTrackedMapOnClient2)
  {
    verifyEntry("client2-value10");
    LOG("VerifyTrackedMapOnClient2 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT1, VerifyTrackedMapOnClient12)
  {
    thread1->stop();
    delete thread1;
    verifyEntry("client2-value10");
    LOG("VerifyTrackedMapOnClient12 completed");
  }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(SERVER, CloseServer1)
  {
    SLEEP(2000);
    if (isLocalServer) {
      CacheHelper::closeServer(1);
      LOG("SERVER1 stopped");
    }
  }
END_TASK_DEFINITION

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

DUNIT_TASK_DEFINITION(CLIENT1, CloseClient1)
  { cleanProc(); }
END_TASK_DEFINITION
DUNIT_TASK_DEFINITION(CLIENT2, CloseClient2)
  { cleanProc(); }
END_TASK_DEFINITION
DUNIT_MAIN
  {
    CALL_TASK(StartLocator);
    CALL_TASK(StartServer1);
    CALL_TASK(StartClient1);
    CALL_TASK(StartClient2);
    CALL_TASK(PutOnClient1);
    CALL_TASK(PutOnClient2);
    CALL_TASK(VerifyOnClient1);
    CALL_TASK(VerifyOnClient2);
    CALL_TASK(VerifyOnClient12);
    CALL_TASK(DestroyOnClient1);
    CALL_TASK(DestroyOnClient2);
    CALL_TASK(VerifyDestroyOnClient1);
    CALL_TASK(VerifyDestroyOnClient2);
    CALL_TASK(VerifyDestroyOnClient12);
    CALL_TASK(PutTrackedMapOnClient1);
    CALL_TASK(PutTrackedMapOnClient2);
    CALL_TASK(VerifyTrackedMapOnClient1);
    CALL_TASK(VerifyTrackedMapOnClient2);
    CALL_TASK(VerifyTrackedMapOnClient12);
    CALL_TASK(CloseClient1);
    CALL_TASK(CloseClient2);
    CALL_TASK(CloseServer1);
    CALL_TASK(CloseLocator);
  }
END_MAIN
