/*
 * 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 "StatisticsManager.hpp"

#include <string>

#include <ace/Guard_T.h>
#include <ace/OS.h>
#include <ace/Thread_Mutex.h>
#include <ace/Time_Value.h>

#include <geode/Exception.hpp>
#include <geode/internal/geode_globals.hpp>

#include "../util/Log.hpp"
#include "AtomicStatisticsImpl.hpp"
#include "GeodeStatisticsFactory.hpp"
#include "OsStatisticsImpl.hpp"

namespace apache {
namespace geode {
namespace statistics {

using client::Exception;
using client::Log;

StatisticsManager::StatisticsManager(
    const char* filePath, const std::chrono::milliseconds sampleInterval,
    bool enabled, CacheImpl* cache, int64_t statFileLimit,
    int64_t statDiskSpaceLimit)
    : m_sampleIntervalMs(sampleInterval),
      m_sampler(nullptr),
      m_adminRegion(nullptr) {
  m_newlyAddedStatsList.reserve(16);  // Allocate initial sizes
  m_statisticsFactory =
      std::unique_ptr<GeodeStatisticsFactory>(new GeodeStatisticsFactory(this));

  try {
    if (m_sampler == nullptr && enabled) {
      m_sampler = new HostStatSampler(filePath, m_sampleIntervalMs, this, cache,
                                      statFileLimit, statDiskSpaceLimit);
      m_sampler->start();
    }
  } catch (...) {
    delete m_sampler;
    throw;
  }
}

void StatisticsManager::forceSample() {
  if (m_sampler) m_sampler->forceSample();
}

StatisticsManager::~StatisticsManager() {
  try {
    // Stop the sampler
    closeSampler();

    // List should be empty if close() is called on each Stats object
    // If this is not done, delete all the pointers
    ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
    int32_t count = static_cast<int32_t>(m_statsList.size());
    if (count > 0) {
      LOGFINEST("~StatisticsManager has found %d leftover statistics:", count);
      std::vector<Statistics*>::iterator iterFind = m_statsList.begin();
      while (iterFind != m_statsList.end()) {
        if (*iterFind != nullptr) {
          std::string temp((*iterFind)->getType()->getName());
          LOGFINEST("Leftover statistic: %s", temp.c_str());
          /* adongre
           * Passing null variable "*iterFind" to function
           * "apache::geode::statistics::StatisticsManager::deleteStatistics(apache::geode::statistics::Statistics
           * *&)",
           * which dereferences it.
           * FIX : Put the call into the if condition
           */
          deleteStatistics(*iterFind);
          *iterFind = nullptr;
        }
        ++iterFind;
      }
      m_statsList.erase(m_statsList.begin(), m_statsList.end());
    }
  } catch (const Exception& ex) {
    Log::warningCatch("~StatisticsManager swallowing Geode exception", ex);

  } catch (const std::exception& ex) {
    std::string what = "~StatisticsManager swallowing std::exception: ";
    what += ex.what();
    Log::warning(what.c_str());

  } catch (...) {
    Log::error("~StatisticsManager swallowing unknown exception");
  }
}

ACE_Recursive_Thread_Mutex& StatisticsManager::getListMutex() {
  return m_statsListLock;
}

void StatisticsManager::closeSampler() {
  if (m_sampler != nullptr) {
    m_sampler->stop();
    delete m_sampler;
    m_sampler = nullptr;
  }
}

void StatisticsManager::addStatisticsToList(Statistics* stat) {
  if (stat) {
    ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
    m_statsList.push_back(stat);

    /* Add to m_newlyAddedStatsList also so that a fresh traversal not needed
    before sampling.
    After writing token to sampled file, stats ptrs will be deleted from list.
    */
    m_newlyAddedStatsList.push_back(stat);
  }
}

int32_t StatisticsManager::getStatListModCount() {
  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
  return static_cast<int32_t>(m_statsList.size());
}

std::vector<Statistics*>& StatisticsManager::getStatsList() {
  return this->m_statsList;
}

std::vector<Statistics*>& StatisticsManager::getNewlyAddedStatsList() {
  return this->m_newlyAddedStatsList;
}

Statistics* StatisticsManager::findFirstStatisticsByType(
    const StatisticsType* type) {
  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
  std::vector<Statistics*>::iterator start = m_statsList.begin();
  while (start != m_statsList.end()) {
    if (!((*start)->isClosed()) && ((*start)->getType() == type)) {
      return *start;
    }
    start++;
  }
  return nullptr;
}

std::vector<Statistics*> StatisticsManager::findStatisticsByType(
    StatisticsType* type) {
  std::vector<Statistics*> hits;

  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);

  std::vector<Statistics*>::iterator start = m_statsList.begin();
  while (start != m_statsList.end()) {
    if (!((*start)->isClosed()) && ((*start)->getType() == type)) {
      hits.push_back(*start);
    }
    start++;
  }
  return hits;
}

std::vector<Statistics*> StatisticsManager::findStatisticsByTextId(
    char* textId) {
  std::vector<Statistics*> hits;

  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);

  std::vector<Statistics*>::iterator start = m_statsList.begin();
  while (start != m_statsList.end()) {
    if (!((*start)->isClosed()) && ((*start)->getTextId() == textId)) {
      hits.push_back(*start);
    }
    start++;
  }
  return hits;
}

std::vector<Statistics*> StatisticsManager::findStatisticsByNumericId(
    int64_t numericId) {
  std::vector<Statistics*> hits;

  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);

  std::vector<Statistics*>::iterator start = m_statsList.begin();
  while (start != m_statsList.end()) {
    if (!((*start)->isClosed()) && ((*start)->getNumericId() == numericId)) {
      hits.push_back(*start);
    }
    start++;
  }
  return hits;
}

Statistics* StatisticsManager::findStatisticsByUniqueId(int64_t uniqueId) {
  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);

  std::vector<Statistics*>::iterator start = m_statsList.begin();
  while (start != m_statsList.end()) {
    if (!((*start)->isClosed()) && ((*start)->getUniqueId() == uniqueId)) {
      Statistics* ret = *start;
      return ret;
    }
    start++;
  }
  return nullptr;
}

void StatisticsManager::deleteStatistics(Statistics*& stat) {
  if (stat->isAtomic()) {
    AtomicStatisticsImpl* ptr = dynamic_cast<AtomicStatisticsImpl*>(stat);
    delete ptr;
  } else {
    OsStatisticsImpl* ptr = dynamic_cast<OsStatisticsImpl*>(stat);
    delete ptr;
  }
  stat = nullptr;
}

}  // namespace statistics
}  // namespace geode
}  // namespace apache
