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

#include <string>

#include <boost/process/environment.hpp>

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

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

namespace apache {
namespace geode {
namespace statistics {

using client::Exception;
using client::IllegalArgumentException;
using client::Log;
using client::OutOfMemoryException;

GeodeStatisticsFactory::GeodeStatisticsFactory(StatisticsManager* statMngr) {
  m_name = "GeodeStatisticsFactory";
  m_id = boost::this_process::get_id();
  m_statsListUniqueId = 1;

  m_statMngr = statMngr;
}

GeodeStatisticsFactory::~GeodeStatisticsFactory() {
  try {
    m_statMngr = nullptr;

    // Clean Map : Delete all the pointers of StatisticsType from the map.
    std::lock_guard<decltype(statsTypeMap)::mutex_type> lock(
        statsTypeMap.mutex());
    if (statsTypeMap.empty()) return;

    for (auto& entry : statsTypeMap) {
      delete entry.second;
    }
    statsTypeMap.clear();

  } catch (const Exception& ex) {
    Log::warningCatch("~GeodeStatisticsFactory swallowing Geode exception", ex);

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

  } catch (...) {
    LOGERROR("~GeodeStatisticsFactory swallowing unknown exception");
  }
}

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

int64_t GeodeStatisticsFactory::getId() const { return m_id; }

Statistics* GeodeStatisticsFactory::createStatistics(StatisticsType* type) {
  return createAtomicStatistics(type, nullptr, 0);
}

Statistics* GeodeStatisticsFactory::createStatistics(
    StatisticsType* type, const std::string& textId) {
  return createAtomicStatistics(type, textId, 0);
}

Statistics* GeodeStatisticsFactory::createStatistics(StatisticsType* type,
                                                     const std::string& textId,
                                                     int64_t numericId) {
  return createAtomicStatistics(type, textId, numericId);
}

Statistics* GeodeStatisticsFactory::createOsStatistics(
    StatisticsType* type, const std::string& textId, int64_t numericId) {
  // Validate input
  if (type == nullptr) {
    throw IllegalArgumentException("StatisticsType* is Null");
  }

  int64_t myUniqueId;
  {
    std::lock_guard<decltype(m_statsListUniqueIdLock)> guard(
        m_statsListUniqueIdLock);
    myUniqueId = m_statsListUniqueId++;
  }

  Statistics* result =
      new OsStatisticsImpl(type, textId, numericId, myUniqueId, this);
  { m_statMngr->addStatisticsToList(result); }

  return result;
}

Statistics* GeodeStatisticsFactory::createAtomicStatistics(
    StatisticsType* type) {
  return createAtomicStatistics(type, nullptr, 0);
}

Statistics* GeodeStatisticsFactory::createAtomicStatistics(
    StatisticsType* type, const std::string& textId) {
  return createAtomicStatistics(type, textId, 0);
}

Statistics* GeodeStatisticsFactory::createAtomicStatistics(
    StatisticsType* type, const std::string& textId, int64_t numericId) {
  // Validate input
  if (type == nullptr) {
    throw IllegalArgumentException("StatisticsType* is Null");
  }
  int64_t myUniqueId;

  {
    std::lock_guard<decltype(m_statsListUniqueIdLock)> guard(
        m_statsListUniqueIdLock);
    myUniqueId = m_statsListUniqueId++;
  }

  Statistics* result =
      new AtomicStatisticsImpl(type, textId, numericId, myUniqueId, this);

  { m_statMngr->addStatisticsToList(result); }

  return result;
}

Statistics* GeodeStatisticsFactory::findFirstStatisticsByType(
    const StatisticsType* type) const {
  return (m_statMngr->findFirstStatisticsByType(type));
}

StatisticsTypeImpl* GeodeStatisticsFactory::addType(StatisticsTypeImpl* st) {
  const auto& name = st->getName();
  try {
    auto status = statsTypeMap.emplace(name, st);
    if (!status.second) {
      throw IllegalArgumentException(
          "GeodeStatisticsFactory::addType: failed to add new type " + name);
    }
  } catch (const std::exception& ex) {
    throw IllegalArgumentException(ex.what());
  } catch (...) {
    throw IllegalArgumentException("addType: unknown exception");
  }
  return st;
}

/**
 * Creates  a StatisticType for the given shared class.
 */
StatisticsType* GeodeStatisticsFactory::createType(
    const std::string& name, const std::string& description,
    StatisticDescriptor** stats, int32_t statsLength) {
  auto st = new StatisticsTypeImpl(name, description, stats, statsLength);

  if (st != nullptr) {
    st = addType(st);
  } else {
    throw OutOfMemoryException(
        "GeodeStatisticsFactory::createType :: out memory");
  }
  return st;
}

StatisticsType* GeodeStatisticsFactory::findType(
    const std::string& name) const {
  auto&& lock = statsTypeMap.make_lock();
  const auto& entry = statsTypeMap.find(name);
  if (entry == statsTypeMap.end()) {
    std::string s = "There is no statistic named \"" + name + "\"";
    return nullptr;
  } else {
    return entry->second;
  }
}

StatisticDescriptor* GeodeStatisticsFactory::createIntCounter(
    const std::string& name, const std::string& description,
    const std::string& units, bool largerBetter) {
  return StatisticDescriptorImpl::createIntCounter(name, description, units,
                                                   largerBetter);
}

StatisticDescriptor* GeodeStatisticsFactory::createLongCounter(
    const std::string& name, const std::string& description,
    const std::string& units, bool largerBetter) {
  return StatisticDescriptorImpl::createLongCounter(name, description, units,
                                                    largerBetter);
}

StatisticDescriptor* GeodeStatisticsFactory::createDoubleCounter(
    const std::string& name, const std::string& description,
    const std::string& units, bool largerBetter) {
  return StatisticDescriptorImpl::createDoubleCounter(name, description, units,
                                                      largerBetter);
}

StatisticDescriptor* GeodeStatisticsFactory::createIntGauge(
    const std::string& name, const std::string& description,
    const std::string& units, bool largerBetter) {
  return StatisticDescriptorImpl::createIntGauge(name, description, units,
                                                 largerBetter);
}

StatisticDescriptor* GeodeStatisticsFactory::createLongGauge(
    const std::string& name, const std::string& description,
    const std::string& units, bool largerBetter) {
  return StatisticDescriptorImpl::createLongGauge(name, description, units,
                                                  largerBetter);
}

StatisticDescriptor* GeodeStatisticsFactory::createDoubleGauge(
    const std::string& name, const std::string& description,
    const std::string& units, bool largerBetter) {
  return StatisticDescriptorImpl::createDoubleGauge(name, description, units,
                                                    largerBetter);
}

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