#include "pch.h"
#include "System/Guid.h"
#include "System/String.h"
#include "System/FormatException.h"
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <cstring>

namespace DotNetDupe {
    namespace System {
        const Guid Guid::Empty = Guid();

        Guid::Guid() {
            for (size_t i = 0; i < 16; ++i) {
                _data[i] = 0;
            }
        }

        Guid::Guid(const Array<uint8_t>& b) {
            if (b.GetLength() != 16) throw ArgumentException("Guid should be 16 bytes.");
            for (size_t i = 0; i < 16; ++i) {
                _data[i] = b[static_cast<int>(i)];
            }
        }

        Guid::Guid(const String& g) {
            String s = g.Replace("{", "").Replace("}", "").Replace("-", "");

            if (s.GetLength() != 32) throw FormatException("Guid string should only contain 32 hexadecimal characters.");

            for (size_t i = 0; i < 16; ++i) {
                unsigned int byteVal;
                String sub = s.Substring(static_cast<int>(i * 2), 2);
#if defined(_WIN32)
                if (sscanf_s(sub.GetRawString(), "%02x", &byteVal) != 1)
#else
                if (sscanf(sub.GetRawString(), "%02x", &byteVal) != 1)
#endif
                    throw FormatException("Guid string should only contain 32 hexadecimal characters.");
                _data[i] = (uint8_t)byteVal;
            }
        }

        Guid Guid::NewGuid() {
            // Very simple random Guid for now
            Array<uint8_t> data(16);
            for (size_t i = 0; i < 16; ++i) {
                data[static_cast<int>(i)] = static_cast<uint8_t>(rand() % 256);
            }
            // Set version 4 and variant
            data[6] = (data[6] & 0x0F) | 0x40;
            data[8] = (data[8] & 0x3F) | 0x80;
            return Guid(data);
        }

        Array<uint8_t> Guid::ToByteArray() const {
            Array<uint8_t> result(16);
            for (size_t i = 0; i < 16; ++i) {
                result[static_cast<int>(i)] = _data[i];
            }
            return result;
        }

        String Guid::ToString() const {
            char buf[37];
            snprintf(buf, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
                _data[0], _data[1], _data[2], _data[3],
                _data[4], _data[5],
                _data[6], _data[7],
                _data[8], _data[9],
                _data[10], _data[11], _data[12], _data[13], _data[14], _data[15]);
            return String(buf);
        }

        bool Guid::operator==(const Guid& other) const {
            return std::memcmp(_data, other._data, 16) == 0;
        }

        bool Guid::operator!=(const Guid& other) const {
            return !(*this == other);
        }
    }
}

Generated by OpenCppCoverage (Version: 0.9.9.0)