#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

#include "LatticeWindow.h"
#include "LatticeWorld.h"

uint8_t ColorMap[64];

static void initColorMap(void);
void fillCircleWorld(uint8_t *world, unsigned int width, unsigned int height,
        unsigned int radius, float emptyDensity);

typedef enum {
    STATUS_SUCCESS,
    STATUS_GLFW_FAILURE,
} StatusCode;

typedef struct {
} WorldState;


const unsigned int WORLD_WIDTH = 1024;
const unsigned int WORLD_HEIGHT = 1024;

#if SIDES==4
    #define SITE_MAX 15
#elif SIDES==6
    #define SITE_MAX 63
#endif

int main(void) {
    uint8_t worldBuf[WORLD_WIDTH * WORLD_HEIGHT];
    unsigned int i, x, y;
    initColorMap();
    /*
    for(x = 1; x < WORLD_WIDTH-1; ++x) {
        for(y = 1; y < WORLD_HEIGHT-1; ++y) {
            if(x >= 250 && x < 350 && y >= 150 && y < 250) {
                worldBuf[x + y * WORLD_WIDTH] = SITE_MAX;
            }
            else {
                unsigned int randval = rand() % 200;
                if(randval > SITE_MAX) {
                    randval = 0;
                }
                worldBuf[x + y * WORLD_WIDTH] = randval;
                //worldBuf[x + y * WORLD_WIDTH] = 0;
            }
        }
    }
    */
    fillCircleWorld(worldBuf, WORLD_WIDTH, WORLD_HEIGHT, 50, 0.1);
    LatticeWindow *window = CreateWindow(WORLD_WIDTH, WORLD_HEIGHT);
    LatticeWorld *world = CreateWorld(WORLD_WIDTH, WORLD_HEIGHT, worldBuf);
    while(GetWindowState(window) == WINDOW_OPEN) {
        uint8_t *buf;
        UpdateWorld(world);
        buf = GetWorldData(world);
        memcpy(worldBuf, buf, sizeof(worldBuf));
        for(i = 0; i < sizeof(worldBuf); ++i) {
            worldBuf[i] = ColorMap[worldBuf[i]];
        }
        DrawFrame(window, worldBuf, WORLD_WIDTH, WORLD_HEIGHT);
    }
    DestroyWindow(window);
    DestroyWorld(world);
}

static void initColorMap(void) {
    unsigned int i;
    for(i = 0; i < sizeof(ColorMap); ++i) {
        unsigned int bitCount = 0;
        unsigned int temp = i;
        while(temp) {
            if(temp & 0x01) {
                ++bitCount;
            }
            temp = temp >> 1;
        }
        ColorMap[i] = bitCount * 40;
    }
}

void fillCircleWorld(uint8_t *world, unsigned int width, unsigned int height,
        unsigned int radius, float emptyDensity) {
    int x, y, x0, y0;
    int i;
    x0 = width/2;
    y0 = height/2;
    for(x = 1; x < width-1; ++x) {
        for(y = 1; y < height-1; ++y) {
            if((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius*radius){
                world[x + y * width] = SITE_MAX;
            }
            else {
                world[x + y * width] = 0;
                for(i = 0; i < 6; ++i) {
                    unsigned int randval = rand();
                    float frand = (float)randval / RAND_MAX;
                    if(frand < emptyDensity) {
                        world[x + y * width] |= (1 << i);;
                    }
                }
            }
        }
    }
}
