/*
 * 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_FWKLIB_FWKOBJECTS_H_
#define GEODE_FWKLIB_FWKOBJECTS_H_

#include <chrono>
#include <vector>
#include <list>
#include <map>

#include <errno.h>

#include <ace/OS.h>

#include <geode/Cache.hpp>
#include <geode/Properties.hpp>
#include <geode/ExpirationAction.hpp>
#include <geode/RegionAttributes.hpp>
#include <geode/RegionAttributesFactory.hpp>
#include <geode/PoolManager.hpp>
#include <geode/internal/chrono/duration.hpp>

#include "fwklib/FwkStrCvt.hpp"
#include "fwklib/FwkLog.hpp"

#include "fwklib/GsRandom.hpp"

#include <xercesc/dom/DOM.hpp>

#define HOSTGROUP_TAG "hostGroup"
#define LOCALFILE_TAG "localFile"
#define DATA_TAG "data"
#define DATASET_TAG "data-set"
#define CLIENTSET_TAG "client-set"
#define TEST_TAG "test"
#define ONEOF_TAG "oneof"
#define LIST_TAG "list"
#define RANGE_TAG "range"
#define SNIPPET_TAG "snippet"
#define REGION_TAG "region"
#define POOL_TAG "pool"
#define TASK_TAG "task"
#define CLIENT_TAG "client"
#define ITEM_TAG "item"
#define REGIONTIMETOLIVE_TAG "region-time-to-live"
#define REGIONIDLETIME_TAG "region-idle-time"
#define ENTRYTIMETOLIVE_TAG "entry-time-to-live"
#define ENTRYIDLETIME_TAG "entry-idle-time"
#define CACHELOADER_TAG "cache-loader"
#define CACHELISTENER_TAG "cache-listener"
#define CACHEWRITER_TAG "cache-writer"
#define PERSISTENCEMANAGER_TAG "persistence-manager"
#define PROPERTIES_TAG "properties"
#define PROPERTY_TAG "property"

#define CLIENT_STATUS_BB "clientStatusBB"

#define FWK_SUCCESS 0
#define FWK_WARNING 1
#define FWK_ERROR 2
#define FWK_SEVERE 3

namespace apache {
namespace geode {
namespace client {
namespace testframework {

using XERCES_CPP_NAMESPACE::chLatin_L;
using XERCES_CPP_NAMESPACE::chLatin_S;
using XERCES_CPP_NAMESPACE::chNull;
using XERCES_CPP_NAMESPACE::DOMAttr;
using XERCES_CPP_NAMESPACE::DOMError;
using XERCES_CPP_NAMESPACE::DOMErrorHandler;
using XERCES_CPP_NAMESPACE::DOMException;
using XERCES_CPP_NAMESPACE::DOMImplementation;
using XERCES_CPP_NAMESPACE::DOMImplementationLS;
using XERCES_CPP_NAMESPACE::DOMImplementationRegistry;
using XERCES_CPP_NAMESPACE::DOMLSParser;
using XERCES_CPP_NAMESPACE::DOMNamedNodeMap;
using XERCES_CPP_NAMESPACE::DOMNode;
using XERCES_CPP_NAMESPACE::DOMText;
using XERCES_CPP_NAMESPACE::XMLException;
using XERCES_CPP_NAMESPACE::XMLPlatformUtils;
using XERCES_CPP_NAMESPACE::XMLString;
using XERCES_CPP_NAMESPACE::XMLUni;

/** @brief Table of object enumeration data types */
typedef enum eFwkDataType {
  DATA_TYPE_NULL,
  DATA_TYPE_CONTENT,
  DATA_TYPE_LIST,
  DATA_TYPE_ONEOF,
  DATA_TYPE_RANGE,
  DATA_TYPE_SNIPPET
} tFwkDataType;

// ----------------------------------------------------------------------------

class FwkObject {
  std::string m_name;

 public:
  FwkObject() {}
  virtual ~FwkObject() {}

  void setName(std::string name) { m_name = name; }
  const std::string& getName() const { return m_name; }

  /** @brief Get key string */
  virtual const std::string& getKey() const = 0;
  virtual void print() const = 0;
};

// ----------------------------------------------------------------------------

/**
 * @class TFwkSet
 *
 * @brief Framework base data object set template
 */

template <class FWK_OBJECT>
class TFwkSet {
 private:
  std::string m_name;
  bool m_deleteOnClear;
  std::vector<const FWK_OBJECT*> m_vec;

 public:
  TFwkSet() : m_deleteOnClear(true) {}

  ~TFwkSet() { clear(); }

  const std::string& getName() const { return m_name; }

  void setName(std::string name) { m_name = name; }

  void setNoDelete() { m_deleteOnClear = false; }

  /** @brief Prints collection of objects */
  void print() const {
    const FWK_OBJECT* obj = getFirst();
    while (obj != nullptr) {
      obj->print();
      obj = getNext(obj);
    }
  }

  /** @brief Find a object in collection
   * @param key Object key to find
   */
  const FWK_OBJECT* find(const std::string& key) const {
    const FWK_OBJECT* obj = nullptr;
    int32_t pos = findIdx(key);
    if (pos != -1) {
      obj = m_vec.at(pos);
    }
    return obj;
  }

  /** @brief Get first object in collection */
  const FWK_OBJECT* getFirst() const {
    const FWK_OBJECT* obj = nullptr;
    int32_t siz = static_cast<int32_t>(m_vec.size());
    if (siz > 0) {
      return m_vec.at(0);
    }
    return obj;
  }

  /** @brief Get next object in collection */
  const FWK_OBJECT* getNext(const FWK_OBJECT* prev) const {
    const FWK_OBJECT* obj = nullptr;
    if (prev == nullptr) {
      return getFirst();
    }
    int32_t siz = static_cast<int32_t>(m_vec.size());
    if (siz > 0) {
      const std::string key = prev->getKey();
      int32_t pos = findIdx(key);
      if (++pos < siz) {
        return m_vec.at(pos);
      }
    }
    return obj;
  }

  /** @brief Clears collection of objects */
  void clear() {
    int32_t siz = static_cast<int32_t>(m_vec.size());
    while (siz > 0) {
      const FWK_OBJECT* obj = m_vec.back();
      m_vec.pop_back();
      if (m_deleteOnClear) {
        delete obj;
      }
      siz = static_cast<int32_t>(m_vec.size());
    }
  }

  /** @brief Add an object
   * @param obj Object to add
   */
  void add(const FWK_OBJECT* obj) {
    if (obj != nullptr) {
      m_vec.push_back(obj);
    }
  }

  const FWK_OBJECT* at(int32_t idx) const {
    if ((idx < 0) || (idx > size())) return nullptr;
    return m_vec.at(idx);
  }

  /** @brief Get count of objects in collection */
  int32_t size() const { return static_cast<int32_t>(m_vec.size()); }

 private:
  int32_t findIdx(const std::string& key) const {
    int32_t idx = -1;
    if (!key.empty()) {
      int32_t pos = 0;
      int32_t max = static_cast<int32_t>(m_vec.size());
      while (pos < max) {
        const FWK_OBJECT* curr = (const FWK_OBJECT*)m_vec.at(pos);
        if (curr->getKey() == key) {
          idx = pos;
          max = -1;
        }
        pos++;
      }
    }
    return idx;
  }
};

// ----------------------------------------------------------------------------

typedef std::vector<std::string> StringVector;

// ----------------------------------------------------------------------------

/** @class XMLStringConverter
 * @brief  This is a simple class that lets us do easy (though not
 * terribly efficient) trancoding of char* data to XMLCh data.
 */
class XMLStringConverter {
 public:
  explicit XMLStringConverter(const char* const toTranscode) {
    m_charForm = nullptr;
    // Call the private transcoding method
    m_unicodeForm = XMLString::transcode(toTranscode);
  }

  explicit XMLStringConverter(const XMLCh* toTranscode) {
    m_unicodeForm = nullptr;
    m_charForm = XMLString::transcode(toTranscode);
  }

  ~XMLStringConverter() {
    if (m_unicodeForm) XMLString::release(&m_unicodeForm);
    if (m_charForm) XMLString::release(&m_charForm);
  }

  /** @brief  get unicode methods */
  const XMLCh* unicodeForm() const { return m_unicodeForm; }

  /** @brief  get char methods */
  std::string charForm() const {
    std::string sCharForm;
    if (m_charForm) sCharForm = m_charForm;
    return sCharForm;
  }

 private:
  XMLCh* m_unicodeForm;
  char* m_charForm;
};

// ----------------------------------------------------------------------------

/** @brief convert XMLCh to a string */
#define XMLChToStr(str) XMLStringConverter(str).charForm()

/** @brief convert string to XMLCh */
#define StrToXMLCh(str) XMLStringConverter(str).unicodeForm()

// ----------------------------------------------------------------------------

class ActionPair {
  std::string m_libraryName;
  std::string m_libraryFunctionName;

  void setLibraryName(std::string name) { m_libraryName = name; }
  void setLibraryFunctionName(std::string name) {
    m_libraryFunctionName = name;
  }

 public:
  explicit ActionPair(const DOMNode* node);

  const char* getLibraryName() { return m_libraryName.c_str(); }
  const char* getLibraryFunctionName() { return m_libraryFunctionName.c_str(); }
};

// ----------------------------------------------------------------------------

class ExpiryAttributes {
  std::chrono::seconds m_timeout;
  ExpirationAction m_action;

  // TODO GEODE-3136: Consider parser
  void setTimeout(std::string str) {
    m_timeout = std::chrono::seconds(FwkStrCvt::toInt32(str));
  }

  void setAction(std::string action) {
    if (action == "invalidate") {
      m_action = ExpirationAction::INVALIDATE;
    } else if (action == "destroy") {
      m_action = ExpirationAction::DESTROY;
    } else if (action == "local-invalidate") {
      m_action = ExpirationAction::LOCAL_INVALIDATE;
    } else if (action == "local-destroy") {
      m_action = ExpirationAction::LOCAL_DESTROY;
    }
  }

 public:
  explicit ExpiryAttributes(const DOMNode* node);

  ExpirationAction getAction() { return m_action; }
  std::chrono::seconds getTimeout() { return m_timeout; }
};

// ----------------------------------------------------------------------------

class PersistManager {
  std::string m_libraryName;
  std::string m_libraryFunctionName;
  std::shared_ptr<Properties> m_properties;

  void setLibraryName(std::string name) { m_libraryName = name; }
  void setLibraryFunctionName(std::string name) {
    m_libraryFunctionName = name;
  }
  void addProperties(const DOMNode* node);
  void addProperty(const DOMNode* node);

 public:
  explicit PersistManager(const DOMNode* node);
  ~PersistManager() { m_properties = nullptr; }

  const char* getLibraryName() { return m_libraryName.c_str(); }
  const char* getLibraryFunctionName() { return m_libraryFunctionName.c_str(); }
  std::shared_ptr<Properties>& getProperties() { return m_properties; }
};

// ----------------------------------------------------------------------------

class Attributes {
  RegionAttributesFactory m_factory;
  bool m_isLocal;
  bool m_withPool;

  void setCachingEnabled(std::string val) {
    m_factory.setCachingEnabled(FwkStrCvt::toBool(val));
  }

  void setLoadFactor(std::string val) {
    m_factory.setLoadFactor(FwkStrCvt::toFloat(val));
  }

  void setConcurrencyLevel(std::string val) {
    m_factory.setConcurrencyLevel(
        static_cast<uint8_t>(FwkStrCvt::toInt32(val)));
  }

  void setLruEntriesLimit(std::string val) {
    m_factory.setLruEntriesLimit(FwkStrCvt::toUInt32(val));
  }

  void setInitialCapacity(std::string val) {
    m_factory.setInitialCapacity(FwkStrCvt::toInt32(val));
  }

  void setCloningEnabled(std::string val) {
    m_factory.setCloningEnabled(FwkStrCvt::toBool(val));
  }

  void setRegionTimeToLive(ExpiryAttributes* val) {
    m_factory.setRegionTimeToLive(val->getAction(), val->getTimeout());
    delete val;
  }

  void setRegionIdleTime(ExpiryAttributes* val) {
    m_factory.setRegionIdleTimeout(val->getAction(), val->getTimeout());
    delete val;
  }
  void setEntryTimeToLive(ExpiryAttributes* val) {
    m_factory.setEntryTimeToLive(val->getAction(), val->getTimeout());
    delete val;
  }
  void setEntryIdleTime(ExpiryAttributes* val) {
    m_factory.setEntryIdleTimeout(val->getAction(), val->getTimeout());
    delete val;
  }

  void setCacheLoader(ActionPair* val) {
    m_factory.setCacheLoader(val->getLibraryName(),
                             val->getLibraryFunctionName());
  }

  void setCacheListener(ActionPair* val) {
    m_factory.setCacheListener(val->getLibraryName(),
                               val->getLibraryFunctionName());
  }

  void setCacheWriter(ActionPair* val) {
    m_factory.setCacheWriter(val->getLibraryName(),
                             val->getLibraryFunctionName());
  }
  void setConcurrencyCheckEnabled(std::string val) {
    m_factory.setConcurrencyChecksEnabled(FwkStrCvt::toBool(val));
  }
  void setPersistenceManager(PersistManager* val) {
    m_factory.setPersistenceManager(val->getLibraryName(),
                                    val->getLibraryFunctionName(),
                                    val->getProperties());
  }

  ExpiryAttributes* getExpiryAttributes(const DOMNode* node);

 public:
  explicit Attributes(const DOMNode* node);

  RegionAttributes getAttributes() { return m_factory.create(); }

  void setPoolName(std::string val) {
    if (!val.empty()) {
      m_factory.setPoolName(val.c_str());
      m_withPool = true;
    } else {
      m_factory.setPoolName(val.c_str());
      m_withPool = false;
    }
  }

  bool isLocal() { return m_isLocal; }

  bool isWithPool() { return m_withPool; }
};
// ----------------------------------------------------------------------------

class FwkRegion {
  std::string m_name;
  Attributes* m_attributes;

  void setName(std::string name) { m_name = name; }
  void setAttributes(Attributes* attributes) { m_attributes = attributes; }

 public:
  explicit FwkRegion(const DOMNode* node);
  ~FwkRegion() {
    if (m_attributes != nullptr) {
      delete m_attributes;
      m_attributes = nullptr;
    }
  }

  const std::string& getName() const { return m_name; }

  Attributes* getAttributes() { return m_attributes; }

  const RegionAttributes getRegionAttributes() const {
    return m_attributes->getAttributes();
  }
  void print() const { FWKINFO("FwkRegion " << m_name); }
};

// ---------------------------------------------------------------------------------

class FwkPool {
  std::string m_name;
  std::shared_ptr<Cache> m_cache;
  PoolManager* m_poolManager;
  PoolFactory m_poolFactory;
  bool m_locators;
  bool m_servers;

  void setName(std::string name) { m_name = name; }
  void setAttributesToFactory(const DOMNode* node);

  void setFreeConnectionTimeout(std::string val) {
    m_poolFactory.setFreeConnectionTimeout(
        apache::geode::internal::chrono::duration::from_string<
            std::chrono::milliseconds>(val));
  }

  void setLoadConditioningInterval(std::string val) {
    m_poolFactory.setLoadConditioningInterval(
        apache::geode::internal::chrono::duration::from_string<
            std::chrono::milliseconds>(val));
  }

  void setSocketBufferSize(std::string val) {
    m_poolFactory.setSocketBufferSize(FwkStrCvt::toInt32(val));
  }

  void setReadTimeout(std::string val) {
    m_poolFactory.setReadTimeout(
        apache::geode::internal::chrono::duration::from_string<
            std::chrono::milliseconds>(val));
  }

  void setMinConnections(std::string val) {
    m_poolFactory.setMinConnections(FwkStrCvt::toInt32(val));
  }

  void setMaxConnections(std::string val) {
    m_poolFactory.setMaxConnections(FwkStrCvt::toInt32(val));
  }

  void setIdleTimeout(std::string val) {
    m_poolFactory.setIdleTimeout(
        apache::geode::internal::chrono::duration::from_string<
            std::chrono::milliseconds>(val));
  }

  void setRetryAttempts(std::string val) {
    m_poolFactory.setRetryAttempts(FwkStrCvt::toInt32(val));
  }

  void setPingInterval(std::string val) {
    m_poolFactory.setPingInterval(
        apache::geode::internal::chrono::duration::from_string<
            std::chrono::milliseconds>(val));
  }

  void setStatisticInterval(std::string val) {
    m_poolFactory.setStatisticInterval(
        apache::geode::internal::chrono::duration::from_string<
            std::chrono::milliseconds>(val));
  }

  void setServerGroup(std::string val) {
    m_poolFactory.setServerGroup(val.c_str());
  }

  void setSubscriptionEnabled(std::string val) {
    m_poolFactory.setSubscriptionEnabled(FwkStrCvt::toBool(val));
  }

  void setSubscriptionRedundancy(std::string val) {
    m_poolFactory.setSubscriptionRedundancy(FwkStrCvt::toInt32(val));
  }

  void setSubscriptionMessageTrackingTimeout(std::string val) {
    m_poolFactory.setSubscriptionMessageTrackingTimeout(
        apache::geode::internal::chrono::duration::from_string<
            std::chrono::milliseconds>(val));
  }

  void setSubscriptionAckInterval(std::string val) {
    m_poolFactory.setSubscriptionAckInterval(
        apache::geode::internal::chrono::duration::from_string<
            std::chrono::milliseconds>(val));
  }

  void setThreadLocalConnections(std::string val) {
    m_poolFactory.setThreadLocalConnections(FwkStrCvt::toBool(val));
  }
  void setPRSingleHopEnabled(std::string val) {
    m_poolFactory.setPRSingleHopEnabled(FwkStrCvt::toBool(val));
  }

  void setLocatorsFlag(std::string val) { m_locators = FwkStrCvt::toBool(val); }

  void setServersFlag(std::string val) { m_servers = FwkStrCvt::toBool(val); }

 public:
  explicit FwkPool(const DOMNode* node);
  ~FwkPool() = default;
  bool isPoolWithLocators() { return m_locators; }
  bool isPoolWithServers() { return m_servers; }

  void addLocator(std::string ep) {
    size_t position = ep.find_first_of(":");
    if (position != std::string::npos) {
      std::string hostname = ep.substr(0, position);
      int portnumber = atoi((ep.substr(position + 1)).c_str());
      m_poolFactory.addLocator(hostname.c_str(), portnumber);
    }
  }

  void addServer(std::string ep) {
    FWKINFO("GG: Adding Server EP:" << ep);
    size_t position = ep.find_first_of(":");
    if (position != std::string::npos) {
      std::string hostname = ep.substr(0, position);
      int portnumber = atoi((ep.substr(position + 1)).c_str());
      m_poolFactory.addServer(hostname.c_str(), portnumber);
    }
  }

  //  std::shared_ptr<Pool> createPoolForPerf() { return
  //  m_poolFactory.create(m_name.c_str()); }

  //  std::shared_ptr<Pool> createPool() const {
  //    if (m_name.empty()) {
  //      FWKEXCEPTION("Pool name not specified.");
  //    } else {
  //      return m_poolFactory.create(m_name.c_str());
  //    }
  //    return nullptr;
  //  }
  const std::string& getName() const { return m_name; }
  void print() const { FWKINFO("FwkPool " << m_name); }
};

// ----------------------------------------------------------------------------

class DataSnippet {
  std::string m_name;
  FwkRegion* m_region;
  FwkPool* m_pool;

  void setName(std::string name) { m_name = name; }
  void setRegion(FwkRegion* region) { m_region = region; }
  void setPool(FwkPool* pool) { m_pool = pool; }

 public:
  explicit DataSnippet(const DOMNode* node);
  ~DataSnippet() {
    if (m_region != nullptr) {
      delete m_region;
      m_region = nullptr;
    }
    if (m_pool != nullptr) {
      delete m_pool;
      m_pool = nullptr;
    }
  }

  std::string& getName() { return m_name; }
  const FwkRegion* getRegion() const { return m_region; }
  const FwkPool* getPool() const { return m_pool; }
  void print() const {
    FWKINFO("Snippet: " << m_name << " has region: ");
    m_region->print();
  }
};

// ----------------------------------------------------------------------------

class DataOneof {
  StringVector m_values;
  std::string m_empty;

 public:
  explicit DataOneof(const DOMNode* node);

  ~DataOneof() { m_values.clear(); }

  const std::string& getValue() const {
    int32_t maxIdx = static_cast<int32_t>(m_values.size()) - 1;
    if (maxIdx < 0) {
      return m_empty;
    }
    return m_values.at(GsRandom::random(maxIdx));
  }

  void addValue(std::string val) { m_values.push_back(val); }
  void print() const {
    FWKINFO("DataOneof has values:");
    int32_t maxIdx = static_cast<int32_t>(m_values.size()) - 1;
    if (maxIdx < 0) {
      return;
    }
    for (int32_t idx = 0; idx <= maxIdx; idx++) {
      FWKINFO(m_values.at(idx));
    }
  }
};

// ----------------------------------------------------------------------------

typedef std::map<ACE_thread_t, int32_t> TlsMap;
typedef std::map<ACE_thread_t, int32_t>::const_iterator TlsMapIter;

class DataList {
  mutable TlsMap m_map;
  StringVector m_values;
  std::string m_empty;

  const std::string& getFirstListItem(ACE_thread_t tid) const {
    StringVector::const_iterator idx = m_values.begin();
    if (idx != m_values.end()) {
      m_map[tid] = 0;
      return (*idx);
    }
    return m_empty;
  }

  const std::string& getNextListItem(TlsMapIter iter) const {
    int32_t idx = (*iter).second;

    if (++idx >= static_cast<int32_t>(m_values.size())) {
      idx = -1;
    }
    m_map[(*iter).first] = idx;
    if (idx > -1) {
      return m_values.at(idx);
    }
    return m_empty;
  }

 public:
  explicit DataList(const DOMNode* node);

  ~DataList() {
    m_map.clear();
    m_values.clear();
  }

  const std::string& getValue() const {
    ACE_thread_t tid = ACE_OS::thr_self();
    TlsMapIter iter = m_map.find(tid);
    if (iter == m_map.end()) {
      // thread not in map, return the first list item
      return getFirstListItem(tid);
    }
    // We have an iterator, return the next in the list
    return getNextListItem(iter);
  }

  void reset() const { m_map.erase(ACE_OS::thr_self()); }
  void addValue(std::string val) { m_values.push_back(val); }
  void print() const {
    FWKINFO("DataList has values:");
    //        ACE_thread_t maxIdx = static_cast<ACE_thread_t> (m_values.size())
    //        - 1;
    //        if ( maxIdx < 0 ) {
    //          return;
    //        }
    //        for ( ACE_thread_t idx = 0; idx <= maxIdx; idx++ ) {
    //          FWKINFO( m_values.at( idx ) );
    //        }
  }
};

// ----------------------------------------------------------------------------

class DataRange {
  double m_low;
  double m_high;
  std::string m_last;

  void setLow(std::string str) { m_low = FwkStrCvt::toDouble(str); }
  void setHigh(std::string str) { m_high = FwkStrCvt::toDouble(str); }
  void setLow(double low) { m_low = low; }
  void setHigh(double high) { m_high = high; }

 public:
  explicit DataRange(const DOMNode* node);

  const std::string getValue() const {
    return FwkStrCvt(GsRandom::random(m_low, m_high)).asString();
  }
  void print() const {
    FWKINFO("DataRange: low = " << m_low << "  high = " << m_high);
  }
};

// ----------------------------------------------------------------------------

/**
 * @class FwkData
 * @brief Framework Data object
 */
class FwkData : public FwkObject {
 public:
  explicit FwkData(const DOMNode* node);

  ~FwkData() {
    if (m_dataList != nullptr) {
      delete m_dataList;
      m_dataList = nullptr;
    }
    if (m_dataOneof != nullptr) {
      delete m_dataOneof;
      m_dataOneof = nullptr;
    }
    if (m_dataRange != nullptr) {
      delete m_dataRange;
      m_dataRange = nullptr;
    }
    if (m_snippet != nullptr) {
      delete m_snippet;
      m_snippet = nullptr;
    }
  }

  void setList(const DataList* dataList) {
    m_dataList = dataList;
    m_dataType = DATA_TYPE_LIST;
  }

  void setOneof(const DataOneof* dataOneof) {
    m_dataOneof = dataOneof;
    m_dataType = DATA_TYPE_ONEOF;
  }

  void setContent(std::string content) {
    m_content = content;
    m_dataType = DATA_TYPE_CONTENT;
  }

  void setRange(DataRange* range) {
    m_dataRange = range;
    m_dataType = DATA_TYPE_RANGE;
  }

  void setSnippet(DataSnippet* snippet) {
    m_snippet = snippet;
    m_dataType = DATA_TYPE_SNIPPET;
  }

  const FwkRegion* getSnippet() const {
    if (m_dataType == DATA_TYPE_SNIPPET) {
      return m_snippet->getRegion();
    }
    return nullptr;
  }

  const FwkPool* getPoolSnippet() const {
    if (m_dataType == DATA_TYPE_SNIPPET) {
      return m_snippet->getPool();
    }
    return nullptr;
  }

  const std::string getValue() const {
    switch (m_dataType) {
      case DATA_TYPE_LIST:
        return m_dataList->getValue();
        break;
      case DATA_TYPE_ONEOF:
        return m_dataOneof->getValue();
        break;
      case DATA_TYPE_RANGE:
        return m_dataRange->getValue();
        break;
      case DATA_TYPE_SNIPPET:
        break;
      default:
        break;
    }
    return m_content;
  }

  const std::string& getContent() const { return m_content; }

  void reset() const {
    if (DATA_TYPE_LIST == m_dataType) {
      m_dataList->reset();
    }
  }

  virtual const std::string& getKey() const { return getName(); }

  void print() const {
    FWKINFO("Data: " << getName() << " has content: ");
    switch (m_dataType) {
      case DATA_TYPE_LIST:
        m_dataList->print();
        break;
      case DATA_TYPE_ONEOF:
        m_dataOneof->print();
        break;
      case DATA_TYPE_RANGE:
        m_dataRange->print();
        break;
      case DATA_TYPE_SNIPPET:
        m_snippet->print();
        break;
      default:
        FWKINFO("Content: " << m_content);
        break;
    }
  }

 private:
  std::string m_content;
  const DataList* m_dataList;
  const DataOneof* m_dataOneof;
  const DataRange* m_dataRange;
  const DataSnippet* m_snippet;

  tFwkDataType m_dataType;
};

// ----------------------------------------------------------------------------

/**
 * @class FwkDataSet
 *
 * @brief Container to hold FwkData objects
 * @see FwkData
 */
class FwkDataSet : public TFwkSet<FwkData> {
 public:
  FwkDataSet() {}
  explicit FwkDataSet(const DOMNode* node);
};

// ----------------------------------------------------------------------------

/**
 * @class FwkClient
 *
 * @brief FwkClient object
 */
class FwkClient : public FwkObject {
 public:
  explicit FwkClient(const DOMNode* node);

  explicit FwkClient(std::string name)
      : m_program(nullptr), m_arguments(nullptr), m_remaining(false) {
    setName(name);
  }

  ~FwkClient() {
    if (m_program != nullptr) {
      free((void*)m_program);
      m_program = nullptr;
    }
    if (m_arguments != nullptr) {
      free((void*)m_arguments);
      m_arguments = nullptr;
    }
  }

  void print() const { FWKINFO("Client: " << getName()); }

  void setProgram(std::string str) {
    if (!str.empty()) m_program = strdup(str.c_str());
  }

  void setArguments(std::string str) {
    if (!str.empty()) m_arguments = strdup(str.c_str());
  }

  void setHost(std::string str) {
    if ((m_host.empty()) && (!str.empty())) m_host = str;
  }

  void setHostGroup(const std::string& grp) { m_hostGroup = grp; }
  const std::string getHostGroup() const { return m_hostGroup; }

  void setRemaining(bool remaining) { m_remaining = remaining; }
  bool getRemaining() const { return m_remaining; }

  const char* getProgram() const { return m_program; }
  const char* getArguments() const { return m_arguments; }
  const std::string& getHost() const { return m_host; }
  virtual const std::string& getKey() const { return getName(); }

 private:
  const char* m_program;
  const char* m_arguments;
  std::string m_hostGroup;
  bool m_remaining;
  std::string m_host;
};

// ----------------------------------------------------------------------------

/**
 * @class FwkClientSet
 *
 * @brief Container to hold FwkClient objects
 * @see FwkClient
 */
class FwkClientSet : public TFwkSet<FwkClient> {
  bool m_exclude;
  int32_t m_count;
  int32_t m_begin;
  std::string m_hostGroup;
  bool m_remaining;

  void addClient(FwkClient* client) { add(client); }

  void setCount(std::string str) { m_count = FwkStrCvt::toInt32(str); }

  void setBegin(std::string str) { m_begin = FwkStrCvt::toInt32(str); }

 public:
  static const std::string m_defaultGroup;

  FwkClientSet()
      : m_exclude(false), m_count(1), m_begin(1), m_remaining(false) {}
  explicit FwkClientSet(const DOMNode* node);

  void setExclude(bool exclude) { m_exclude = exclude; }

  void setExclude(std::string str) { m_exclude = FwkStrCvt::toBool(str); }

  void setHostGroup(const std::string str) { m_hostGroup = str; }

  bool getExclude() const { return m_exclude; }
  int32_t getCount() const { return m_count; }
  int32_t getBegin() const { return m_begin; }
  std::string getHostGroup() const { return m_hostGroup; }

  void setRemaining(bool remaining) { m_remaining = remaining; }
  void setRemaining(std::string str) { m_remaining = FwkStrCvt::toBool(str); }
  bool getRemaining() const { return m_remaining; }

  void print() const {
    FWKINFO("ClientSet exclude: " << getExclude() << "  count: " << getCount()
                                  << "  begin: " << getBegin());
    TFwkSet<FwkClient>::print();
  }
};

// ----------------------------------------------------------------------------

typedef int32_t (*FwkAction)(const char* taskId);

typedef std::list<uint32_t> TaskClientIdxList;

// ----------------------------------------------------------------------------
class FwkTest;

/**
 * @class FwkTask
 *
 * @brief FwkTask object
 */
class FwkTask : public FwkObject {
 public:
  explicit FwkTask(const DOMNode* node);

  ~FwkTask() {
    if (m_clientSet != nullptr) {
      delete m_clientSet;
      m_clientSet = nullptr;
    }
    if (m_dataSet != nullptr) {
      delete m_dataSet;
      m_dataSet = nullptr;
    }
    m_clients.clear();
  }

  /** @brief Get number of times task has ran */
  uint32_t getTimesRan() const { return m_timesRan; }

  /** @brief Increment number of times task has ran */
  void incTimesRan() { m_timesRan++; }

  /** @brief reset number of times task has ran to zero*/
  void resetTimesRan() { m_timesRan = 0; }

  /** @brief Get number of threads task should run on */
  int32_t getThreadCount() const { return m_threadCount; }

  /** @brief Is this task to run if test has failures? */
  bool continueOnError() const { return m_continue; }

  /** @brief Get number of times to run task */
  uint32_t getTimesToRun() const { return m_timesToRun; }

  /** @brief Get action string */
  std::string getAction() const { return m_action; }

  /** @brief Get class string */
  std::string getClass() const { return m_class; }

  /** @brief Get container string */
  std::string getContainer() const { return m_container; }

  /** @brief Get seconds to wait */
  uint32_t getWaitTime() const { return m_waitTime; }

  /** @brief Is this task to run parallel with other tasks? */
  bool isParallel() const { return m_parallel; }

  /** brief Get FwkDataSet pointer */
  const FwkDataSet* getDataSet(const char* name) const;

  /** brief Get FwkData pointer */
  const FwkData* getData(const char* name) const;

  /** brief Get char pointer */
  const std::string getStringValue(const char* name) const {
    const FwkData* data = getData(name);
    if (data) {
      return data->getValue();
    }
    return m_empty;
  }

  /** brief Get int32_t seconds in time string */
  int32_t getTimeValue(const char* name) const {
    return FwkStrCvt::toSeconds(getStringValue(name));
  }

  /** brief Get int32_t */
  int32_t getIntValue(const char* name) const {
    return FwkStrCvt::toInt32(getStringValue(name));
  }

  /** brief Get bool */
  bool getBoolValue(const char* name) const {
    return FwkStrCvt::toBool(getStringValue(name));
  }

  /** brief Get char pointer */
  const FwkRegion* getSnippet(const std::string& name) const {
    const FwkRegion* value = nullptr;
    const FwkData* data = getData(name.c_str());
    if (data) {
      value = data->getSnippet();
    }
    return value;
  }

  const FwkPool* getPoolSnippet(const std::string& name) const {
    const FwkPool* value = nullptr;
    const FwkData* data = getData(name.c_str());
    if (data) {
      value = data->getPoolSnippet();
    }
    return value;
  }

  void resetValue(const char* name) const {
    FwkData* data = const_cast<FwkData*>(getData(name));
    if (data != nullptr) data->reset();
  }

  TaskClientIdxList* getTaskClients() { return &m_clients; }

  const std::string& getTaskId() const { return m_id; }

  virtual const std::string& getKey() const { return m_id; }

  void setParent(FwkTest* parent) { m_parent = parent; }

  FwkClientSet* getClientSet() { return m_clientSet; }

  void print() const {
    FWKINFO("Task: " << m_id << "  " << m_container << "  " << m_class << "  "
                     << m_action << "  WaitTime: " << m_waitTime
                     << "  TimesToRun: " << m_timesToRun << "  Threads: "
                     << m_threadCount << "  Parallel: " << m_parallel
                     << "  ContinueOnError: " << m_continue);
    if (m_clientSet != nullptr) {
      FWKINFO("Clients: ");
      m_clientSet->print();
    }
    if (m_dataSet != nullptr) {
      FWKINFO("Data: ");
      m_dataSet->print();
    }
    FWKINFO("End Task: " << m_id);
  }

  void setKey(int32_t cnt);

  /** @brief Get number of times to run task */
  void setTimesToRun(uint32_t cnt) { m_timesToRun = cnt; }

 private:
  void setAction(std::string action) { m_action = action; }

  void setClass(std::string clas) { m_class = clas; }

  void setContainer(std::string container) { m_container = container; }

  void setWaitTime(std::string waitTime) {
    m_waitTime = FwkStrCvt::toSeconds(waitTime.c_str());
  }

  /** @brief Get number of times to run task */
  void setTimesToRun(std::string str) {
    m_timesToRun = FwkStrCvt::toUInt32(str);
  }

  void setParallel(std::string str) { m_parallel = FwkStrCvt::toBool(str); }

  void setContinueOnError(std::string str) {
    m_continue = FwkStrCvt::toBool(str);
  }

  /** @brief Set number of threads task should run on */
  void setThreadCount(std::string str) {
    m_threadCount = FwkStrCvt::toInt32(str);
  }

  void setDataSet(FwkDataSet* dataSet) {
    if (m_dataSet == nullptr) m_dataSet = dataSet;
  }

  /** @brief Add ClientSet
   * @param set ClientSet to add
   */
  void addClientSet(FwkClientSet* set) {
    const FwkClient* client = set->getFirst();
    while (client != nullptr) {
      addClient(client);
      client = set->getNext(client);
    }
    if (set->getExclude()) {
      m_clientSet->setExclude(true);
    }
  }

  void addClient(const FwkClient* client) {
    if (m_clientSet == nullptr) {
      m_clientSet = new FwkClientSet();
    }
    m_clientSet->add(client);
  }

  void addData(FwkData* data) {
    if (m_dataSet == nullptr) {
      m_dataSet = new FwkDataSet();
    }
    m_dataSet->add(data);
  }

  std::string m_action;
  std::string m_class;
  std::string m_container;
  // UNUSED FwkAction m_func;
  uint32_t m_waitTime;
  uint32_t m_timesToRun;
  int32_t m_threadCount;
  bool m_parallel;
  std::string m_id;
  uint32_t m_timesRan;
  bool m_continue;

  FwkClientSet* m_clientSet;
  FwkDataSet* m_dataSet;

  FwkTest* m_parent;

  TaskClientIdxList m_clients;

  std::string m_empty;
};

// ----------------------------------------------------------------------------

/**
 * @class FwkTaskSet
 *
 * @brief Container to hold FwkTask objects
 * @see FwkTask
 */
class FwkTaskSet : public TFwkSet<FwkTask> {};

// ----------------------------------------------------------------------------
class TestDriver;

/**
 * @class FwkTest
 *
 * @brief FwkTest object
 */
class FwkTest : public FwkObject {
 public:
  explicit FwkTest(const DOMNode* node);

  /** brief Get FwkDataSet pointer */
  const FwkDataSet* getDataSet(const char* name) const;

  /** brief Get FwkData pointer */
  const FwkData* getData(const char* name) const;

  /** @brief Get description string */
  const char* getDescription() const { return m_description.c_str(); }

  /** @brief Get wait time */
  uint32_t getWaitTime() const { return m_waitTime; }

  /** @brief Get number of times to run task */
  uint32_t getTimesToRun() const { return m_timesToRun; }

  const FwkTask* getFirst() { return m_taskSet.getFirst(); }

  const FwkTask* getNext(const FwkTask* prev) {
    return m_taskSet.getNext(prev);
  }

  const FwkTask* getTaskById(std::string& id) {
    FwkTask* task = const_cast<FwkTask*>(m_taskSet.getFirst());
    while (task != nullptr) {
      if (task->getTaskId() == id) {
        return task;
      }
      task = const_cast<FwkTask*>(m_taskSet.getNext(task));
    }
    return task;
  }

  const FwkTask* find(const char* name) { return m_taskSet.find(name); }

  size_t getCount() const { return m_taskSet.size(); }

  virtual const std::string& getKey() const { return m_id; }

  void print() const {
    FWKINFO("Test: " << m_id << "  " << m_description
                     << "  WaitTime: " << m_waitTime);
    FWKINFO("Tasks: ");
    m_taskSet.print();
    FWKINFO("End Test: " << m_id);
  }

  void setParent(TestDriver* parent) { m_parent = parent; }

  void setKey(int32_t cnt) {
    if (!m_id.empty()) return;
    std::ostringstream ostr;
    ostr << getName() << "::" << cnt;
    m_id = ostr.str();
  }

  /** @brief Get number of times to run task */
  void setTimesToRun(std::string str) {
    m_timesToRun = FwkStrCvt::toUInt32(str);
  }

 private:
  void setWaitTime(std::string waitTime) {
    m_waitTime = FwkStrCvt::toSeconds(waitTime);
  }

  void setDescription(std::string description) { m_description = description; }

  void addTask(FwkTask* task) {
    m_taskSet.add(task);
    task->setParent(this);
  }

  std::string m_id;
  std::string m_description;
  uint32_t m_waitTime;
  uint32_t m_timesToRun;
  FwkTaskSet m_taskSet;
  TestDriver* m_parent;
};

// ----------------------------------------------------------------------------

/**
 * @class FwkTestSet
 *
 * @brief Container to hold FwkTest objects
 * @see FwkTest
 */
class FwkTestSet : public TFwkSet<FwkTest> {};

// ----------------------------------------------------------------------------

class LocalFile : public FwkObject {
  std::string m_description;
  std::string m_content;
  bool m_append;

  void setContent(std::string content) { m_content = content; }
  void setDescription(std::string description) { m_description = description; }
  void setAppend(std::string append) { m_append = FwkStrCvt::toBool(append); }

 public:
  explicit LocalFile(const DOMNode* node);

  const std::string& getContent() const { return m_content; }

  const std::string& getKey() const { return getName(); }

  bool getAppend() const { return m_append; }

  void print() const {
    FWKINFO("LocalFile: " << getName() << " append: " << getAppend()
                          << " has content: " << getContent());
  }
};

// ----------------------------------------------------------------------------

class LocalFileSet : public TFwkSet<LocalFile> {};

// ----------------------------------------------------------------------------

class FwkDomErrorHandler : public DOMErrorHandler {
 public:
  FwkDomErrorHandler() : m_hadErrors(false) {}
  ~FwkDomErrorHandler() = default;

  bool hadErrors() const { return m_hadErrors; }
  bool handleError(const DOMError& domError);
  void resetErrors() { m_hadErrors = false; }

 private:
  bool m_hadErrors;
};

// ----------------------------------------------------------------------------

class TestDriver {
  LocalFileSet m_localFiles;
  FwkDataSet m_data;
  std::map<std::string, FwkDataSet*> m_dataSetMap;
  std::vector<FwkClientSet*> m_clientSets;
  FwkClientSet m_clients;
  FwkTestSet m_tests;
  FwkTaskSet m_tasks;
  std::string m_empty;
  StringVector m_hostGroups;

  void addHostGroup(std::string name) { m_hostGroups.push_back(name); }

  void addLocalFile(LocalFile* file) { m_localFiles.add(file); }

  void addData(FwkData* data) { m_data.add(data); }

  void addDataSet(FwkDataSet* dataSet) {
    m_dataSetMap[dataSet->getName()] = dataSet;
  }

  void addClientSet(FwkClientSet* clientSet) {
    m_clientSets.push_back(clientSet);
    FwkClient* client = const_cast<FwkClient*>(clientSet->getFirst());
    std::string grp = clientSet->getHostGroup();
    bool remaining = clientSet->getRemaining();
    while (client != nullptr) {
      client->setHostGroup(grp);
      client->setRemaining(remaining);
      m_clients.add(client);
      client = const_cast<FwkClient*>(clientSet->getNext(client));
    }
  }

  void addTest(FwkTest* test) {
    m_tests.add(test);
    test->setParent(this);
    test->setKey(m_tests.size());
    const FwkTask* task = test->getFirst();
    int32_t cnt = 1;
    while (task != nullptr) {
      (const_cast<FwkTask*>(task))->setKey(cnt++);
      m_tasks.add(task);
      task = test->getNext(task);
    }
  }

  void clearClientSets() {
    int32_t siz = static_cast<int32_t>(m_clientSets.size());
    while (siz > 0) {
      const FwkClientSet* obj = m_clientSets.back();
      m_clientSets.pop_back();
      delete obj;
      siz = static_cast<int32_t>(m_clientSets.size());
    }
  }

  void clearDataSets() {
    std::map<std::string, FwkDataSet*>::iterator iter;
    iter = m_dataSetMap.begin();
    while (iter != m_dataSetMap.end()) {
      const FwkDataSet* obj = (*iter).second;
      delete obj;
      m_dataSetMap.erase(iter);
      iter = m_dataSetMap.begin();
    }
  }

  void writeLocalFile(const LocalFile* fil) {
    const char* mode;
    std::string what("write");
    if (fil->getAppend()) {
      mode = "ab";
      what = "append";
    } else {
      mode = "wb";
    }
    errno = 0;
    FILE* out = fopen(fil->getName().c_str(), mode);
    if (!out) {
      int32_t err = errno;
      FWKEXCEPTION("Unable to open file " << fil->getName() << " with mode: "
                                          << what << " error: " << err);
    }
    FWKDEBUG("Opened local file: " << fil->getName() << " to " << what
                                   << " content::>" << fil->getContent()
                                   << "<::");
    fprintf(out, "%s", fil->getContent().c_str());
    fclose(out);
  }

 public:
  explicit TestDriver(const char* file);
  ~TestDriver() {
    m_clients.setNoDelete();
    m_tasks.setNoDelete();
    clearClientSets();
    clearDataSets();
  }

  void fromXmlNode(const DOMNode* node);

  void writeFiles() {
    const LocalFile* fil = m_localFiles.getFirst();
    //        FILE * out = fopen( "local.files", "wb" );
    while (fil != nullptr) {
      writeLocalFile(fil);
      //          fprintf( out, "%s\n", fil->getName().c_str() );
      fil = m_localFiles.getNext(fil);
    }
    //        fclose( out );
  }

  FwkClientSet* getClients() { return &m_clients; }

  const FwkTask* getTaskById(std::string id) {
    const FwkTask* task = m_tasks.getFirst();
    while (task != nullptr) {
      if (id == task->getTaskId()) return task;
      task = m_tasks.getNext(task);
    }
    return nullptr;
  }

  const StringVector& getHostGroups() { return m_hostGroups; }

  const FwkTest* nextTest(const FwkTest* test) const {
    return m_tests.getNext(test);
  }

  const FwkTest* firstTest() const { return m_tests.getFirst(); }

  const LocalFile* nextLocalFile(const LocalFile* file) const {
    return m_localFiles.getNext(file);
  }

  const LocalFile* firstLocalFile() const { return m_localFiles.getFirst(); }

  /** brief Get FwkDataSet pointer */
  const FwkDataSet* getDataSet(const char* name) const {
    if (name == nullptr) return nullptr;

    std::map<std::string, FwkDataSet*>::const_iterator iter =
        m_dataSetMap.find(name);

    if (iter != m_dataSetMap.end()) {
      return (*iter).second;
    }
    return nullptr;
  }

  /** brief Get FwkData pointer */
  const FwkData* getData(const char* name) const { return m_data.find(name); }

  /** brief Get char pointer */
  const std::string getStringValue(const char* name) const {
    const FwkData* data = getData(name);
    if (data) {
      return data->getValue();
    }
    return m_empty;
  }

  /** brief Get int32_t seconds in time string */
  int32_t getTimeValue(const char* name) const {
    return FwkStrCvt::toSeconds(getStringValue(name));
  }

  /** brief Get int32_t */
  int32_t getIntValue(const char* name) const {
    return FwkStrCvt::toInt32(getStringValue(name));
  }

  void print() const {
    FWKINFO("TestDriver:   LocalFiles:");
    m_localFiles.print();
    FWKINFO("TestDriver:   Data:");
    m_data.print();
    FWKINFO("TestDriver:   DataSets: <skipping>");
    FWKINFO("TestDriver:   Clients:");
    m_clients.print();
    FWKINFO("TestDriver:   Tests:");
    m_tests.print();
  }
};

// ----------------------------------------------------------------------------

}  // namespace testframework
}  // namespace client
}  // namespace geode
}  // namespace apache

#endif  // GEODE_FWKLIB_FWKOBJECTS_H_
