/*
 * 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 "fw_dunit.hpp"
#include "ThinClientHelper.hpp"
#include <ace/Task.h>
#include <ace/Recursive_Thread_Mutex.h>

using apache::geode::client::Exception;

class GetRegionThread : public ACE_Task_Base {
 public:
  bool m_running;
  std::string m_path;
  std::string m_subPath;
  bool m_regionCreateDone;
  bool m_subRegionCreateDone;
  ACE_Recursive_Thread_Mutex m_mutex;
  GetRegionThread(const char *path, const char *subPath)
      : m_running(false),
        m_path(path),
        m_subPath(subPath),
        m_regionCreateDone(false),
        m_subRegionCreateDone(false),
        m_mutex() {}
  int svc(void) {
    while (m_running == true) {
      SLEEP(40);
      try {
        auto rptr = getHelper()->getRegion(m_path.c_str());
        if (rptr != nullptr) {
          ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_mutex);
          ASSERT(m_regionCreateDone == true, "regionCreate Not Done");
        }
      } catch (Exception &ex) {
        LOG(ex.what());
        continue;
      } catch (std::exception &ex) {
        LOG(ex.what());
        continue;
      } catch (...) {
        LOG("unknown exception");
        continue;
      }
      try {
        auto rptr = getHelper()->getRegion(m_subPath.c_str());
        if (rptr != nullptr) {
          ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_mutex);
          ASSERT(m_subRegionCreateDone == true, "subRegionCreate Not Done");
          return 0;
        }
      } catch (Exception &ex) {
        LOG(ex.what());
      } catch (std::exception &ex) {
        LOG(ex.what());
      } catch (...) {
        LOG("getRegion: unknown exception");
      }
    }
    return 0;
  }
  void setRegionFlag() {
    ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_mutex);
    m_regionCreateDone = true;
  }
  void setSubRegionFlag() {
    ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_mutex);
    m_subRegionCreateDone = true;
  }
  void start() {
    m_running = true;
    activate();
  }
  void stop() {
    m_running = false;
    wait();
  }
};

static int numberOfLocators = 1;
bool isLocalServer = true;
bool isLocator = true;
const char *locHostPort =
    CacheHelper::getLocatorHostPort(isLocator, isLocalServer, numberOfLocators);
GetRegionThread *getThread = nullptr;
std::shared_ptr<Region> regionPtr;
DUNIT_TASK(s1p1, Setup)
  {
    CacheHelper::initLocator(1);
    CacheHelper::initServer(1, "cacheserver_notify_subscription.xml",
                            locHostPort);
    LOG("SERVER started");
  }
ENDTASK

/* setup a normal region */
DUNIT_TASK(s2p2, CreateNormalRegion)
  {
    initClientWithPool(true, "__TEST_POOL1__", locHostPort, "ServerGroup1",
                       nullptr, 0, true);
    LOG("create normal region");
    getThread =
        new GetRegionThread("DistRegionAck", "DistRegionAck/AuthSubregion");
    getThread->start();
    regionPtr = getHelper()->createPooledRegion(
        "DistRegionAck", USE_ACK, locHostPort, "__TEST_POOL1__", true, true);
    getThread->setRegionFlag();
    RegionAttributesFactory regionAttributesFactory;
    auto regionAttributes = regionAttributesFactory.create();
    getThread->setSubRegionFlag();
    LOG("create normal region successful");
  }
END_TASK(CreateNormalRegion)

DUNIT_TASK(s2p2, CloseCache2)
  {
    getThread->stop();
    delete getThread;
    cleanProc();
  }
END_TASK(CloseCache2)

DUNIT_TASK(s1p1, CloseCache)
  {
    CacheHelper::closeServer(1);
    LOG("SERVER closed");
  }
ENDTASK
