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

#include <atomic>

#include <ace/OS_NS_stdio.h>

#include <geode/internal/geode_globals.hpp>

#include "../Assert.hpp"
#include "StatisticDescriptorImpl.hpp"
#include "StatisticsTypeImpl.hpp"

namespace apache {
namespace geode {
namespace statistics {

using client::IllegalArgumentException;

int64_t AtomicStatisticsImpl::calcNumericId(StatisticsFactory* system,
                                            int64_t userValue) {
  int64_t result;
  if (userValue != 0) {
    result = userValue;
  } else {
    result = system->getId();
  }
  return result;
}

std::string AtomicStatisticsImpl::calcTextId(StatisticsFactory* system,
                                             const std::string& userValue) {
  if (!userValue.empty()) {
    return userValue;
  } else {
    if (system != nullptr) {
      return system->getName();
    } else {
      return "";
    }
  }
}

AtomicStatisticsImpl::AtomicStatisticsImpl(StatisticsType* typeArg,
                                           const std::string& textIdArg,
                                           int64_t numericIdArg,
                                           int64_t uniqueIdArg,
                                           StatisticsFactory* system)

{
  try {
    this->textIdStr = calcTextId(system, textIdArg);
    this->numericId = calcNumericId(system, numericIdArg);
    this->uniqueId = uniqueIdArg;
    this->closed = false;
    this->statsType = dynamic_cast<StatisticsTypeImpl*>(typeArg);
    GF_D_ASSERT(this->statsType != nullptr);
    int32_t intCount = statsType->getIntStatCount();
    int32_t longCount = statsType->getLongStatCount();
    int32_t doubleCount = statsType->getDoubleStatCount();

    if (intCount > 0) {
      intStorage = new std::atomic<int32_t>[intCount];
      for (int32_t i = 0; i < intCount; i++) {
        intStorage[i] = 0;  // Un-initialized state
      }

    } else {
      intStorage = nullptr;
    }
    if (longCount > 0) {
      longStorage = new std::atomic<int64_t>[longCount];
      for (int32_t i = 0; i < longCount; i++) {
        longStorage[i] = 0;  // Un-initialized state
      }

    } else {
      longStorage = nullptr;
    }
    if (doubleCount > 0) {
      doubleStorage = new std::atomic<double>[doubleCount];
      for (int32_t i = 0; i < doubleCount; i++) {
        doubleStorage[i] = 0;  // Un-initialized state
      }
    } else {
      doubleStorage = nullptr;
    }
  } catch (...) {
    statsType = nullptr;  // Will be deleted by the class who calls this ctor
  }
}

AtomicStatisticsImpl::~AtomicStatisticsImpl() noexcept {
  try {
    statsType = nullptr;
    if (intStorage != nullptr) {
      delete[] intStorage;
      intStorage = nullptr;
    }
    if (longStorage != nullptr) {
      delete[] longStorage;
      longStorage = nullptr;
    }
    if (doubleStorage != nullptr) {
      delete[] doubleStorage;
      doubleStorage = nullptr;
    }
  } catch (...) {
  }
}

bool AtomicStatisticsImpl::isShared() const { return false; }

bool AtomicStatisticsImpl::isAtomic() const {
  return true;  // will always be true for this class
}

void AtomicStatisticsImpl::close() {
  // Just mark closed,Will be actually deleted when token written in archive
  // file.
  closed = true;
}

void AtomicStatisticsImpl::_setInt(int32_t offset, int32_t value) {
  if (offset >= statsType->getIntStatCount()) {
    char s[128] = {'\0'};
    ACE_OS::snprintf(
        s, 128, "setInt:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }
  intStorage[offset] = value;
}

void AtomicStatisticsImpl::_setLong(int32_t offset, int64_t value) {
  if (offset >= statsType->getLongStatCount()) {
    char s[128] = {'\0'};

    ACE_OS::snprintf(
        s, 128, "setLong:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }

  longStorage[offset] = value;
}

void AtomicStatisticsImpl::_setDouble(int32_t offset, double value) {
  if (offset >= statsType->getDoubleStatCount()) {
    char s[128] = {'\0'};
    ACE_OS::snprintf(
        s, 128,
        "setDouble:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }

  doubleStorage[offset] = value;
}

int32_t AtomicStatisticsImpl::_getInt(int32_t offset) const {
  if (offset >= statsType->getIntStatCount()) {
    char s[128] = {'\0'};
    ACE_OS::snprintf(
        s, 128, "getInt:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }

  return intStorage[offset];
}

int64_t AtomicStatisticsImpl::_getLong(int32_t offset) const {
  if (offset >= statsType->getLongStatCount()) {
    char s[128] = {'\0'};
    ACE_OS::snprintf(
        s, 128, "getLong:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }
  return longStorage[offset];
}

double AtomicStatisticsImpl::_getDouble(int32_t offset) const {
  if (offset >= statsType->getDoubleStatCount()) {
    char s[128] = {'\0'};
    ACE_OS::snprintf(
        s, 128,
        "getDouble:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }
  return doubleStorage[offset];
}

int64_t AtomicStatisticsImpl::_getRawBits(
    const StatisticDescriptor* statDscp) const {
  const auto stat = dynamic_cast<const StatisticDescriptorImpl*>(statDscp);
  switch (stat->getTypeCode()) {
    case INT_TYPE:
      return getInt(stat->getId());

    case LONG_TYPE:
      return _getLong(stat->getId());

    case DOUBLE_TYPE: {
      double value = _getDouble(stat->getId());
      int64_t* temp = reinterpret_cast<int64_t*>(&value);
      return *temp;
    }
    default:
      return 0;
      /*throw RuntimeException("unexpected stat descriptor type code: " +
                                stat->getTypeCode());*/
  }
}

int64_t AtomicStatisticsImpl::getRawBits(
    const StatisticDescriptor* descriptor) const {
  if (isOpen()) {
    return _getRawBits(descriptor);
  } else {
    return 0;
  }
}

int32_t AtomicStatisticsImpl::_incInt(int32_t offset, int32_t delta) {
  if (offset >= statsType->getIntStatCount()) {
    char s[128] = {'\0'};
    ACE_OS::snprintf(
        s, 128, "incInt:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }

  return (intStorage[offset] += delta);
}

int64_t AtomicStatisticsImpl::_incLong(int32_t offset, int64_t delta) {
  if (offset >= statsType->getLongStatCount()) {
    char s[128] = {'\0'};
    /* adongre  - Coverity II
     * CID 29273: Calling risky function (SECURE_CODING)[VERY RISKY]. Using
     * "sprintf" can cause a
     * buffer overflow when done incorrectly. Because sprintf() assumes an
     * arbitrarily long string,
     * callers must be careful not to overflow the actual space of the
     * destination.
     * Use snprintf() instead, or correct precision specifiers.
     * Fix : using ACE_OS::snprintf
     */
    // sprintf(s, "incLong:The id (%d) of the Statistic Descriptor is not valid
    // ", offset);

    ACE_OS::snprintf(
        s, 128, "incLong:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }

  return (longStorage[offset] += delta);
}

double AtomicStatisticsImpl::_incDouble(int32_t offset, double delta) {
  if (offset >= statsType->getDoubleStatCount()) {
    char s[128] = {'\0'};
    ACE_OS::snprintf(
        s, 128,
        "incDouble:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }

  double expected = doubleStorage[offset];
  double value;
  do {
    value = expected + delta;
  } while (!doubleStorage[offset].compare_exchange_weak(expected, value));

  return value;
}

int32_t AtomicStatisticsImpl::nameToId(const std::string& name) const {
  return statsType->nameToId(name);
}

StatisticDescriptor* AtomicStatisticsImpl::nameToDescriptor(
    const std::string& name) const {
  return statsType->nameToDescriptor(name);
}

bool AtomicStatisticsImpl::isClosed() const { return closed; }

bool AtomicStatisticsImpl::isOpen() const { return !closed; }

StatisticsType* AtomicStatisticsImpl::getType() const { return statsType; }

const std::string& AtomicStatisticsImpl::getTextId() const { return textIdStr; }

int64_t AtomicStatisticsImpl::getNumericId() const { return numericId; }

int64_t AtomicStatisticsImpl::getUniqueId() const { return uniqueId; }

void AtomicStatisticsImpl::setInt(const std::string& name, int32_t value) {
  int32_t id = getIntId(nameToDescriptor(name));
  setInt(id, value);
}

void AtomicStatisticsImpl::setInt(const StatisticDescriptor* descriptor,
                                  int32_t value) {
  int32_t id = getIntId(descriptor);
  setInt(id, value);
}

void AtomicStatisticsImpl::setInt(int32_t id, int32_t value) {
  if (isOpen()) {
    _setInt(id, value);
  }
}

void AtomicStatisticsImpl::setLong(const std::string& name, int64_t value) {
  setLong(nameToDescriptor(name), value);
}

void AtomicStatisticsImpl::setLong(const StatisticDescriptor* descriptor,
                                   int64_t value) {
  setLong(getLongId(descriptor), value);
}

void AtomicStatisticsImpl::setLong(int32_t id, int64_t value) {
  if (isOpen()) {
    _setLong(id, value);
  }
}

void AtomicStatisticsImpl::setDouble(const std::string& name, double value) {
  setDouble(nameToDescriptor(name), value);
}

void AtomicStatisticsImpl::setDouble(const StatisticDescriptor* descriptor,
                                     double value) {
  setDouble(getDoubleId(descriptor), value);
}

void AtomicStatisticsImpl::setDouble(int32_t id, double value) {
  if (isOpen()) {
    _setDouble(id, value);
  }
}

int32_t AtomicStatisticsImpl::getInt(const std::string& name) const {
  int32_t id = getIntId(nameToDescriptor(name));
  return getInt(id);
}

int32_t AtomicStatisticsImpl::getInt(
    const StatisticDescriptor* descriptor) const {
  int32_t id = getIntId(descriptor);
  return getInt(id);
}

int32_t AtomicStatisticsImpl::getInt(int32_t id) const {
  if (isOpen()) {
    return _getInt(id);
  } else {
    return 0;
  }
}

int64_t AtomicStatisticsImpl::getLong(const std::string& name) const {
  return getLong(nameToDescriptor(name));
}

int64_t AtomicStatisticsImpl::getLong(
    const StatisticDescriptor* descriptor) const {
  return getLong(getLongId(descriptor));
}

int64_t AtomicStatisticsImpl::getLong(int32_t id) const {
  if (isOpen()) {
    return _getLong(id);
  } else {
    return 0;
  }
}

double AtomicStatisticsImpl::getDouble(const std::string& name) const {
  return getDouble(nameToDescriptor(name));
}

double AtomicStatisticsImpl::getDouble(
    const StatisticDescriptor* descriptor) const {
  return getDouble(getDoubleId(descriptor));
}

double AtomicStatisticsImpl::getDouble(int32_t id) const {
  if (isOpen()) {
    return _getDouble(id);
  } else {
    return 0;
  }
}

int32_t AtomicStatisticsImpl::incInt(const std::string& name, int32_t delta) {
  int32_t id = getIntId(nameToDescriptor(name));
  return incInt(id, delta);
}

int32_t AtomicStatisticsImpl::incInt(const StatisticDescriptor* descriptor,
                                     int32_t delta) {
  int32_t id = getIntId(descriptor);
  return incInt(id, delta);
}

int32_t AtomicStatisticsImpl::incInt(int32_t id, int32_t delta) {
  if (isOpen()) {
    return _incInt(id, delta);
  } else {
    return 0;
  }
}

int64_t AtomicStatisticsImpl::incLong(const std::string& name, int64_t delta) {
  return incLong(nameToDescriptor(name), delta);
}

int64_t AtomicStatisticsImpl::incLong(const StatisticDescriptor* descriptor,
                                      int64_t delta) {
  return incLong(getLongId(descriptor), delta);
}

int64_t AtomicStatisticsImpl::incLong(int32_t id, int64_t delta) {
  if (isOpen()) {
    return _incLong(id, delta);
  } else {
    return 0;
  }
}

double AtomicStatisticsImpl::incDouble(const std::string& name, double delta) {
  return incDouble(nameToDescriptor(name), delta);
}

double AtomicStatisticsImpl::incDouble(const StatisticDescriptor* descriptor,
                                       double delta) {
  return incDouble(getDoubleId(descriptor), delta);
}

double AtomicStatisticsImpl::incDouble(int32_t id, double delta) {
  if (isOpen()) {
    return _incDouble(id, delta);
  } else {
    return 0;
  }
}

int32_t AtomicStatisticsImpl::getIntId(
    const StatisticDescriptor* descriptor) const {
  const auto realDescriptor =
      dynamic_cast<const StatisticDescriptorImpl*>(descriptor);
  return realDescriptor->checkInt();
}

int32_t AtomicStatisticsImpl::getLongId(
    const StatisticDescriptor* descriptor) const {
  const auto realDescriptor =
      dynamic_cast<const StatisticDescriptorImpl*>(descriptor);
  return realDescriptor->checkLong();
}

int32_t AtomicStatisticsImpl::getDoubleId(
    const StatisticDescriptor* descriptor) const {
  const auto realDescriptor =
      dynamic_cast<const StatisticDescriptorImpl*>(descriptor);
  return realDescriptor->checkDouble();
}

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