/*
 * 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_INTERNAL_UTILS_H_
#define GEODE_INTERNAL_UTILS_H_

#include <chrono>
#include <memory>
#include <random>
#include <string>
#include <typeinfo>
#include <unordered_set>

#include <geode/CacheableString.hpp>
#include <geode/DataOutput.hpp>
#include <geode/ExceptionTypes.hpp>
#include <geode/SystemProperties.hpp>
#include <geode/internal/geode_base.hpp>
#include <geode/internal/geode_globals.hpp>

#include "DistributedSystem.hpp"
#include "statistics/Statistics.hpp"
#include "util/Log.hpp"

#ifdef __GNUC__
extern "C" {
#include <cxxabi.h>
}
#endif

namespace apache {
namespace geode {
namespace client {
class APACHE_GEODE_EXPORT Utils {
  /**
   * utilities
   *
   */
 public:
  /**
   * Get the value of an environment variable.
   * On windows the maximum length of value supported is 8191.
   */
  static std::string getEnv(const char* varName);
  static int32_t getLastError();

#ifdef __GNUC__
  inline static char* _gnuDemangledName(const char* typeIdName, size_t& len) {
    int status;
    char* demangledName =
        abi::__cxa_demangle(typeIdName, nullptr, &len, &status);
    if (status == 0 && demangledName != nullptr) {
      return demangledName;
    }
    return nullptr;
  }
#endif

  inline static void demangleTypeName(const char* typeIdName,
                                      std::string& str) {
#ifdef __GNUC__
    size_t len;
    char* demangledName = _gnuDemangledName(typeIdName, len);
    if (demangledName != nullptr) {
      str.append(demangledName, len);
      free(demangledName);
      return;
    }
#endif
    str.append(typeIdName);
  }

  inline static std::string demangleTypeName(const char* typeIdName) {
#ifdef __GNUC__
    size_t len;
    char* demangledName = _gnuDemangledName(typeIdName, len);
    if (demangledName != nullptr) {
      auto str = std::string(demangledName, len);
      free(demangledName);
      return str;
    }
#endif
    return std::string(typeIdName);
  }

  /**
   * The only operations that is well defined on the result is "asChar".
   */
  inline static std::string nullSafeToString(
      const std::shared_ptr<CacheableKey>& key) {
    std::string result;
    if (key) {
      result = key->toString();
    } else {
      result = "(null)";
    }
    return result;
  }

  static std::string nullSafeToString(const std::shared_ptr<Cacheable>& val) {
    std::string result;
    if (val) {
      if (const auto key = std::dynamic_pointer_cast<CacheableKey>(val)) {
        result = nullSafeToString(key);
      } else {
        return result = val->toString();
      }
    } else {
      result = "(null)";
    }

    return result;
  }

  static int64_t startStatOpTime();

  // Check objectSize() implementation return value and log a warning at most
  // once.
  inline static size_t checkAndGetObjectSize(
      const std::shared_ptr<Cacheable>& theObject) {
    auto objectSize = theObject->objectSize();
    static bool youHaveBeenWarned = false;
    if (objectSize == 0 && !youHaveBeenWarned) {
      LOGWARN(
          "Object size for Heap LRU returned by %s is 0 (zero). Even for empty "
          "objects the size returned should be at least one (1 byte).",
          theObject->toString().c_str());
      youHaveBeenWarned = true;
    }
    return objectSize;
  }

  static void updateStatOpTime(statistics::Statistics* m_regionStats,
                               int32_t statId, int64_t start);

  static void parseEndpointNamesString(
      std::string endpoints, std::unordered_set<std::string>& endpointNames);

  static void parseEndpointString(const char* endpoints, std::string& host,
                                  uint16_t& port);

  static std::string convertHostToCanonicalForm(const char* endpoints);

  static char* copyString(const char* str);

  /**
   * Convert the byte array to a string as "%d %d ...".
   * <code>maxLength</code> as zero implies no limit.
   */
  static std::string convertBytesToString(const uint8_t* bytes, size_t length,
                                          size_t maxLength = _GF_MSG_LIMIT);

  /**
   * lib should be in the form required by ACE_DLL, typically just like
   * specifying
   * a
   * lib in java System.loadLibrary( "x" ); Where x is a component of the name
   * lib<x>.so on unix, or <x>.dll on windows.
   */
  static void* getFactoryFunction(const std::string& lib,
                                  const std::string& funcName);

  /**
   * Convert the byte array to a string as "%d %d ...".
   * <code>maxLength</code> as zero implies no limit.
   */
  static std::string convertBytesToString(const int8_t* bytes, size_t length,
                                          size_t maxLength = _GF_MSG_LIMIT);

  /**
   * Convert the byte array to a string as "%d %d ...".
   * <code>maxLength</code> as zero implies no limit.
   */
  inline static std::string convertBytesToString(
      const char* bytes, size_t length, size_t maxLength = _GF_MSG_LIMIT) {
    return convertBytesToString(reinterpret_cast<const uint8_t*>(bytes), length,
                                maxLength);
  }
};

// Generate random numbers 0 to max-1
class RandGen {
 public:
  template <typename T, class G = std::default_random_engine>
  inline T operator()(T max) {
    return std::uniform_int_distribution<T>{0, max - 1}(generator<G>());
  }

 private:
  template <class G>
  inline G& generator() {
    static thread_local G generator(std::random_device{}());
    return generator;
  }
};

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

#endif  // GEODE_INTERNAL_UTILS_H_
