#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "md5.h"
#include "xoroLib.h"

enum{
    TERRACOTTA,
    ORANGE_TERRACOTTA,
    YELLOW_TERRACOTTA,
    BROWN_TERRACOTTA,
    RED_TERRACOTTA,
    WHITE_TERRACOTTA,
    LIGHT_GRAY_TERRACOTTA
};

void md5NoiseCalc(Xoroshiro* xr, char* name)
{
    uint64_t xhi = 0;
    uint64_t xlo = 0;

    uint8_t hash[16];
    MD5_CTX ctx;
    md5_init(&ctx);
    md5_update(&ctx, name, strlen(name));
    md5_final(&ctx, hash);

    for(int i = 0; i < 8; i++)
    {
        xlo |= (uint64_t)hash[i] << (8 * (7 - i));
        xhi |= (uint64_t)hash[i + 8] << (8 * (7 - i));
    }
    xr->lo ^= xlo;
    xr->hi ^= xhi;
}

void makeBands(Xoroshiro* xr, int* clayBands, int baseWidth, int replaceWith)
{
    int bandCount = xNextInt(xr, 15 - 6 + 1) + 6;

    for(int i = 0; i < bandCount; i++)
    {
        int width = baseWidth + xNextInt(xr, 3);
        int start = xNextInt(xr, 192);
        for (int j = 0; start + j < 192 && j < width; j++) {
            clayBands[start + j] = replaceWith;
        }
    }


}

void generateBands(Xoroshiro* xr, int* clayBands)
{
    //replace with memset
    for(int i = 0; i < 192; i++) clayBands[i] = TERRACOTTA;

    //add orange terracotta
    for (int i = 0; i < 192; i++) {
        i += xNextInt(xr, 5) + 1;
        if (i < 192) {
            clayBands[i] = ORANGE_TERRACOTTA;
        }
    }

    makeBands(xr, clayBands, 1, YELLOW_TERRACOTTA);
    makeBands(xr, clayBands, 2, BROWN_TERRACOTTA);
    makeBands(xr, clayBands, 1, RED_TERRACOTTA);

    int whiteBandCount = xNextInt(xr, 15 - 9 + 1) + 9;

    int ix = 0;
    for (int start = 0; ix < whiteBandCount && start < 192; start += xNextInt(xr, 16) + 4) {
        clayBands[start] = WHITE_TERRACOTTA;
        if (start - 1 > 0 && xNextBoolean(xr)) {
            clayBands[start - 1] = LIGHT_GRAY_TERRACOTTA;
        }

        if (start + 1 < 192 && xNextBoolean(xr)) {
            clayBands[start + 1] = LIGHT_GRAY_TERRACOTTA;
        }

        ix++;
    }
}

void printColors(int* clayBands)
{
    for(int i = 191; i > 0; i--)
    {
        switch(clayBands[i])
        {
            case TERRACOTTA:
                printf("\e[0;30m");
                break;
            case ORANGE_TERRACOTTA:
                printf("\e[0;32m");
                break;
            case YELLOW_TERRACOTTA:
                printf("\e[0;33m");
                break;
            case BROWN_TERRACOTTA:
                printf("\e[0;35m");
                break;
            case RED_TERRACOTTA:
                printf("\e[0;31m");
                break;
            case WHITE_TERRACOTTA:
                printf("\e[0;37m");
                break;
            case LIGHT_GRAY_TERRACOTTA:
                printf("\e[0;36m");
                break;
        }
        printf("%d\n", clayBands[i]);        
    }
    printf("\e[0m");
}

int main()
{
    Xoroshiro xr;
    xSetSeed(&xr, 694201337);

    //forkPositional
    {
        uint64_t xlo = xNextLong(&xr);
        uint64_t xhi = xNextLong(&xr);
        xr.lo = xlo;
        xr.hi = xhi;
    }

    //these are the same, i am leaving the md5 in for
    //a more vanilla version
    //md5NoiseCalc(&xr, "minecraft:clay_bands");
    xr.lo ^= 0x16568f44636e3bc9;
    xr.hi ^= 0xc1fdd67395e0296c;

    int clayBands[192];
    generateBands(&xr, clayBands);

    //for(int i = 0; i < 192; i++) printf("%d", clayBands[i]);
    printColors(clayBands);
    //printf("\n");
}