#include <frostbite2D/types/uuid.h>
#include <cstdio>
#include <sstream>
#include <iomanip>

namespace frostbite2D {

UUID UUID::generate() {
  std::array<uint8_t, 16> data;
  for (int i = 0; i < 16; ++i) {
    data[i] = static_cast<uint8_t>(rand() % 256);
  }

  data[6] = (data[6] & 0x0F) | 0x40;
  data[8] = (data[8] & 0x3F) | 0x80;

  return UUID(data);
}

UUID UUID::fromString(const std::string& str) {
  if (str.length() != 36) {
    return UUID{};
  }

  std::array<uint8_t, 16> data{};
  std::stringstream ss(str);
  char dash;
  for (int i = 0; i < 16; ++i) {
    int byte;
    ss >> std::hex >> byte;
    data[i] = static_cast<uint8_t>(byte);
    if (i < 15) {
      ss >> dash;
    }
  }

  return UUID(data);
}

std::string UUID::toString() const {
  const auto& data = data_;
  std::stringstream ss;
  ss << std::hex << std::setfill('0')
     << std::setw(2) << static_cast<int>(data[0])
     << std::setw(2) << static_cast<int>(data[1])
     << std::setw(2) << static_cast<int>(data[2])
     << std::setw(2) << static_cast<int>(data[3])
     << '-'
     << std::setw(2) << static_cast<int>(data[4])
     << std::setw(2) << static_cast<int>(data[5])
     << '-'
     << std::setw(2) << static_cast<int>(data[6])
     << std::setw(2) << static_cast<int>(data[7])
     << '-'
     << std::setw(2) << static_cast<int>(data[8])
     << std::setw(2) << static_cast<int>(data[9])
     << '-'
     << std::setw(2) << static_cast<int>(data[10])
     << std::setw(2) << static_cast<int>(data[11])
     << std::setw(2) << static_cast<int>(data[12])
     << std::setw(2) << static_cast<int>(data[13])
     << std::setw(2) << static_cast<int>(data[14])
     << std::setw(2) << static_cast<int>(data[15]);
  return ss.str();
}

} // namespace frostbite2D
