
#include "uuid.h"

void uuid_unpack(const uuid16_t uuid, struct uuid_RFC4122 *rfc)
{
    rfc->time_low = (uuid[0]<<24)|(uuid[1]<<16)|(uuid[2]<<8)|(uuid[3]<<0);
    rfc->time_mid                             = (uuid[4]<<8)|(uuid[5]<<0);
    rfc->time_hi_and_version                  = (uuid[6]<<8)|(uuid[7]<<0);
    rfc->clock_seq                            = (uuid[8]<<8)|(uuid[9]<<0);
    memcpy(rfc->node, &uuid[10], 6);
}

void uuid_packet(uuid16_t uuid, const struct uuid_RFC4122 *rfc)
{
    uuid[0] = (uint8_t)(rfc->time_low>>24)&0xFF;
    uuid[1] = (uint8_t)(rfc->time_low>>16)&0xFF;
    uuid[2] = (uint8_t)(rfc->time_low>>8)&0xFF;
    uuid[3] = (uint8_t)(rfc->time_low>>0)&0xFF;

    uuid[4] = (uint8_t)(rfc->time_mid>>8)&0xFF;
    uuid[5] = (uint8_t)(rfc->time_mid>>0)&0xFF;

    uuid[6] = (uint8_t)(rfc->time_hi_and_version>>8)&0xFF;
    uuid[7] = (uint8_t)(rfc->time_hi_and_version>>0)&0xFF;

    uuid[8] = (uint8_t)(rfc->clock_seq>>8)&0xFF;
    uuid[9] = (uint8_t)(rfc->clock_seq>>0)&0xFF;

    memcpy(&uuid[10], rfc->node, 6);
}


void uuid_generate_random(uuid16_t out, uint16_t N)
{
    struct uuid_RFC4122 rfc;
    uuid16_t uuid;
    srand((int32_t)time(0));
    for (uint16_t i = 0; i < N; i++)
    {
        for (uint8_t x = 0; x < sizeof(uuid); ++x)
        {
            uuid[x] = rand() % 256;
        }

        uuid_unpack(uuid, &rfc);
        rfc.clock_seq = (rfc.clock_seq & 0x3FFF) | 0x8000;
        rfc.time_hi_and_version = (rfc.time_hi_and_version & 0x0FFF) | 0x4000;
        uuid_packet(out, &rfc);

        out += sizeof(uuid16_t);
    }
}


char* makeUUID(uint8_t* uuid)
{
    uuid16_t out;
    struct uuid_RFC4122 rfc;
    {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);

        rfc.time_low = ts.tv_sec;
        rfc.time_hi_and_version = ts.tv_nsec / 1000000;
        rfc.time_mid = (ts.tv_nsec /1000)% 1000;
        rfc.clock_seq = ts.tv_nsec % 1000;    
        srand((uint32_t)time(0));
        for (int i = 0; i < 6; i++)
        {
            rfc.node[i] = rand() % 256;
        }
    }
    // 00000000-0000-0000-0309-000000000000
    sprintf((char *)uuid,
        "%08x-%02x%02x-%02x%02x-%02x%02x-%04x%04x%04x", // UUID = 36 B
        rfc.time_low,
        rfc.node[0],
        rfc.node[1],
        rfc.node[2],
        rfc.node[3],
        rfc.node[4],
        rfc.node[5],
        rfc.time_hi_and_version,
        rfc.time_mid,
        rfc.clock_seq
    );
    return (char*)uuid;
}