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

#include "../util/Log.hpp"
#include "StatisticDescriptorImpl.hpp"
#include "StatisticsTypeImpl.hpp"
#include "ace/OS.h"

namespace apache {
namespace geode {
namespace statistics {

using client::IllegalArgumentException;

/**
 * An implementation of {@link Statistics} that stores its statistics
 * in local  memory and does not support atomic operations.
 *
 */

//////////////////////  Static Methods  //////////////////////

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

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

///////////////////////  Constructors  ///////////////////////

/**
 * Creates a new statistics instance of the given type
 *
 * @param type
 *        A description of the statistics
 * @param textId
 *        Text that identifies this statistic when it is monitored
 * @param numericId
 *        A number that displayed when this statistic is monitored
 * @param uniqueId
 *        A number that uniquely identifies this instance
 * @param system
 *        The distributed system that determines whether or not these
 *        statistics are stored (and collected) in local memory
 */
OsStatisticsImpl::OsStatisticsImpl(StatisticsType* typeArg,
                                   const std::string& textIdArg,
                                   int64_t numericIdArg, int64_t uniqueIdArg,
                                   StatisticsFactory* system)
    : statsType(dynamic_cast<StatisticsTypeImpl*>(typeArg)),
      textId(calcTextId(system, textIdArg)) {
  this->numericId = calcNumericId(system, numericIdArg);
  this->uniqueId = uniqueIdArg;
  this->closed = false;
  ;
  /* adongre
   * CID 28981: Uninitialized pointer field (UNINIT_CTOR)
   */
  doubleStorage = nullptr;
  intStorage = nullptr;
  longStorage = nullptr;

  if (statsType != nullptr) {
    int32_t intCount = statsType->getIntStatCount();
    int32_t longCount = statsType->getLongStatCount();
    int32_t doubleCount = statsType->getDoubleStatCount();
    if (intCount > 0) {
      intStorage = new 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 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 double[doubleCount];
      for (int32_t i = 0; i < doubleCount; i++) {
        doubleStorage[i] = 0;  // Un-initialized state
      }
    } else {
      doubleStorage = nullptr;
    }
  }  // if(statsType == nullptr)
}

OsStatisticsImpl::~OsStatisticsImpl() 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 (...) {
    LOGERROR("Exception in ~OsStatisticsImpl");
  }
}

//////////////////////  Instance Methods  //////////////////////

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

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

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

////////////////////////  store() Methods  ///////////////////////

void OsStatisticsImpl::_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 OsStatisticsImpl::_setLong(int32_t offset, int64_t value) {
  if (offset >= statsType->getLongStatCount()) {
    char s[128] = {'\0'};
    /* adongre  - Coverity II
     * CID 29275: 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, "setLong:The id (%d) of the Statistic Descriptor is not valid
    // ", offset);
    ACE_OS::snprintf(
        s, 128, "setLong:The id (%d) of the Statistic Descriptor is not valid ",
        offset);
    throw IllegalArgumentException(s);
  }
  longStorage[offset] = value;
}

void OsStatisticsImpl::_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;
}

///////////////////////  get() Methods  ///////////////////////

int32_t OsStatisticsImpl::_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 OsStatisticsImpl::_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 OsStatisticsImpl::_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 OsStatisticsImpl::_getRawBits(
    const StatisticDescriptor* statDscp) const {
  const auto stat = dynamic_cast<const StatisticDescriptorImpl*>(statDscp);
  // dynamic cast is giving problems , so a normal cast was used
  // StatisticDescriptorImpl* stat  = (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());*/
  }
}
////////////////////////  inc() Methods  ////////////////////////

int32_t OsStatisticsImpl::_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);
  }

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

int64_t OsStatisticsImpl::_incLong(int32_t offset, int64_t delta) {
  if (offset >= statsType->getLongStatCount()) {
    char s[128] = {'\0'};
    /* adongre  - Coverity II
     * CID 29274: 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);
  }
  longStorage[offset] += delta;
  return longStorage[offset];
}

double OsStatisticsImpl::_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);
  }
  doubleStorage[offset] += delta;
  return doubleStorage[offset];
}

//////////////////////  Instance Methods  //////////////////////

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

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

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

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

////////////////////////  attribute Methods  ///////////////////////

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

const std::string& OsStatisticsImpl::getTextId() const { return textId; }

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

/**
 * Gets the unique id for this resource
 */
int64_t OsStatisticsImpl::getUniqueId() const { return uniqueId; }
////////////////////////  set() Methods  ///////////////////////

void OsStatisticsImpl::setInt(const std::string& name, int32_t value) {
  setInt(nameToDescriptor(name), value);
}

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

void OsStatisticsImpl::setInt(int32_t id, int32_t value) {
  if (isOpen()) {
    _setInt(id, value);
  }
}
////////////////////////////////LONG METHODS/////////////////////////////

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

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

void OsStatisticsImpl::setLong(int32_t id, int64_t value) {
  if (isOpen()) {
    _setLong(id, value);
  }
}
////////////////////////////////////////DOUBLE METHODS////////////////////

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

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

void OsStatisticsImpl::setDouble(int32_t id, double value) {
  if (isOpen()) {
    _setDouble(id, value);
  }
}
//////////////////////////Get INT Methods/////////////////////////////////////
int32_t OsStatisticsImpl::getInt(const std::string& name) const {
  return getInt(nameToDescriptor(name));
}

int32_t OsStatisticsImpl::getInt(const StatisticDescriptor* descriptor) const {
  return getInt(getIntId(descriptor));
}

int32_t OsStatisticsImpl::getInt(int32_t id) const {
  if (isOpen()) {
    return _getInt(id);
  } else {
    LOGWARN("os statistics is closed");
    return 0;
  }
}

/////////////////////////////////////////Get Long
/// Methods///////////////////////////////

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

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

int64_t OsStatisticsImpl::getLong(int32_t id) const {
  if (isOpen()) {
    return _getLong(id);
  } else {
    return 0;
  }
}
/////////////////////////////////Get DOUBLE Methods
/////////////////////////////////
double OsStatisticsImpl::getDouble(const std::string& name) const {
  return getDouble(nameToDescriptor(name));
}

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

double OsStatisticsImpl::getDouble(int32_t id) const {
  if (isOpen()) {
    return _getDouble(id);
  } else {
    return 0;
  }
}
//////////////////////////////Get RAW BIT
/// methods////////////////////////////////

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

///////////////////////// INC INT //////////////////////////////////////////////
int32_t OsStatisticsImpl::incInt(const std::string& name, int32_t delta) {
  return incInt(nameToDescriptor(name), delta);
}

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

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

//// //////////////// INC LONG ///////////////////////////////////

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

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

int64_t OsStatisticsImpl::incLong(int32_t id, int64_t delta) {
  if (isOpen()) {
    return _incLong(id, delta);
  } else {
    return 0;
  }
}
////////////////////////////  INC DOUBLE //////////////////////////////////////

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

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

double OsStatisticsImpl::incDouble(int32_t id, double delta) {
  if (isOpen()) {
    return _incDouble(id, delta);
  } else {
    return 0;
  }
}
/////////////////////////// GET ID /////////////////////////////////////////

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

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

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

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