/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmCryptoHash.h"

#include <cassert>

#include <cm/memory>

#include <cm3p/kwiml/int.h>
#include <cm3p/rhash.h>

#include "cmsys/FStream.hxx"

static unsigned int const cmCryptoHashAlgoToId[] = {
  /* clang-format needs this comment to break after the opening brace */
  RHASH_MD5,      //
  RHASH_SHA1,     //
  RHASH_SHA224,   //
  RHASH_SHA256,   //
  RHASH_SHA384,   //
  RHASH_SHA512,   //
  RHASH_SHA3_224, //
  RHASH_SHA3_256, //
  RHASH_SHA3_384, //
  RHASH_SHA3_512
};

static int cmCryptoHash_rhash_library_initialized;

static rhash cmCryptoHash_rhash_init(unsigned int id)
{
  if (!cmCryptoHash_rhash_library_initialized) {
    cmCryptoHash_rhash_library_initialized = 1;
    rhash_library_init();
  }
  return rhash_init(id);
}

cmCryptoHash::cmCryptoHash(Algo algo)
  : Id(cmCryptoHashAlgoToId[algo])
  , CTX(cmCryptoHash_rhash_init(this->Id))
{
}

cmCryptoHash::~cmCryptoHash()
{
  rhash_free(this->CTX);
}

std::unique_ptr<cmCryptoHash> cmCryptoHash::New(cm::string_view algo)
{
  if (algo == "MD5") {
    return cm::make_unique<cmCryptoHash>(AlgoMD5);
  }
  if (algo == "SHA1") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA1);
  }
  if (algo == "SHA224") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA224);
  }
  if (algo == "SHA256") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA256);
  }
  if (algo == "SHA384") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA384);
  }
  if (algo == "SHA512") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA512);
  }
  if (algo == "SHA3_224") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA3_224);
  }
  if (algo == "SHA3_256") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA3_256);
  }
  if (algo == "SHA3_384") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA3_384);
  }
  if (algo == "SHA3_512") {
    return cm::make_unique<cmCryptoHash>(AlgoSHA3_512);
  }
  return std::unique_ptr<cmCryptoHash>(nullptr);
}

std::string cmCryptoHash::GetHashAlgoName() const
{
#ifndef CMAKE_USE_SYSTEM_LIBRHASH
  static_assert(RHASH_HASH_COUNT == 10, "Update switch statement!");
#endif
  switch (this->Id) {
    case RHASH_MD5:
      return "MD5";
    case RHASH_SHA1:
      return "SHA1";
    case RHASH_SHA224:
      return "SHA224";
    case RHASH_SHA256:
      return "SHA256";
    case RHASH_SHA384:
      return "SHA384";
    case RHASH_SHA512:
      return "SHA512";
    case RHASH_SHA3_224:
      return "SHA3_224";
    case RHASH_SHA3_256:
      return "SHA3_256";
    case RHASH_SHA3_384:
      return "SHA3_384";
    case RHASH_SHA3_512:
      return "SHA3_512";
  }
  assert(false);
  return "UNKNOWN";
}

bool cmCryptoHash::IntFromHexDigit(char input, char& output)
{
  if (input >= '0' && input <= '9') {
    output = static_cast<char>(input - '0');
    return true;
  }
  if (input >= 'a' && input <= 'f') {
    output = static_cast<char>(input - 'a' + 0xA);
    return true;
  }
  if (input >= 'A' && input <= 'F') {
    output = static_cast<char>(input - 'A' + 0xA);
    return true;
  }
  return false;
}

std::string cmCryptoHash::ByteHashToString(
  const std::vector<unsigned char>& hash)
{
  // Map from 4-bit index to hexadecimal representation.
  static char const hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
                                '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

  std::string res;
  res.reserve(hash.size() * 2);
  for (unsigned char v : hash) {
    res.push_back(hex[v >> 4]);
    res.push_back(hex[v & 0xF]);
  }
  return res;
}

std::vector<unsigned char> cmCryptoHash::ByteHashString(cm::string_view input)
{
  this->Initialize();
  this->Append(input);
  return this->Finalize();
}

std::vector<unsigned char> cmCryptoHash::ByteHashFile(const std::string& file)
{
  cmsys::ifstream fin(file.c_str(), std::ios::in | std::ios::binary);
  if (fin) {
    this->Initialize();
    {
      // Should be efficient enough on most system:
      KWIML_INT_uint64_t buffer[512];
      char* buffer_c = reinterpret_cast<char*>(buffer);
      unsigned char const* buffer_uc =
        reinterpret_cast<unsigned char const*>(buffer);
      // This copy loop is very sensitive on certain platforms with
      // slightly broken stream libraries (like HPUX).  Normally, it is
      // incorrect to not check the error condition on the fin.read()
      // before using the data, but the fin.gcount() will be zero if an
      // error occurred.  Therefore, the loop should be safe everywhere.
      while (fin) {
        fin.read(buffer_c, sizeof(buffer));
        if (int gcount = static_cast<int>(fin.gcount())) {
          this->Append(buffer_uc, gcount);
        }
      }
    }
    if (fin.eof()) {
      // Success
      return this->Finalize();
    }
    // Finalize anyway
    this->Finalize();
  }
  // Return without success
  return std::vector<unsigned char>();
}

std::string cmCryptoHash::HashString(cm::string_view input)
{
  return ByteHashToString(this->ByteHashString(input));
}

std::string cmCryptoHash::HashFile(const std::string& file)
{
  return ByteHashToString(this->ByteHashFile(file));
}

void cmCryptoHash::Initialize()
{
  rhash_reset(this->CTX);
}

void cmCryptoHash::Append(void const* buf, size_t sz)
{
  rhash_update(this->CTX, buf, sz);
}

void cmCryptoHash::Append(cm::string_view input)
{
  rhash_update(this->CTX, input.data(), input.size());
}

std::vector<unsigned char> cmCryptoHash::Finalize()
{
  std::vector<unsigned char> hash(rhash_get_digest_size(this->Id), 0);
  rhash_final(this->CTX, hash.data());
  return hash;
}

std::string cmCryptoHash::FinalizeHex()
{
  return cmCryptoHash::ByteHashToString(this->Finalize());
}
