#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <omp.h>

#include "noiseLib.h"
#include "md5.h"

int isIceberg(DoublePerlinNoise* dpnIcebergPillar, DoublePerlinNoise* dpnIcebergSurface, float x, float z)
{
    /*
    double iceberg = Math.min(
        Math.abs(this.icebergSurfaceNoise.getValue(blockX, 0.0, blockZ) * 8.25),
        this.icebergPillarNoise.getValue(blockX * 1.28, 0.0, blockZ * 1.28) * 15.0
    );
    */
    //is this coord an iceberg?
    float icebergSurfaceNoise = sampleDoublePerlin(dpnIcebergSurface, 6, x, 0.0, z);
    float icebergPillarNoise = sampleDoublePerlin(dpnIcebergPillar, 8, x*1.28, 0.0, z*1.28);
    float sampo = fmin(fabs(icebergSurfaceNoise * 8.25), icebergPillarNoise * 15.0);
    
    //printf("%f %f %f\n", icebergPillarNoise, icebergSurfaceNoise, sampo);

    return 1.8 < sampo;
}

int isValidSeed(DoublePerlinNoise* dpnIcebergPillar, DoublePerlinNoise* dpnIcebergSurface)
{
    for(int z = 0; z < 64; z++)
    {
        for(int x = 0; x < 64; x++)
        {
            if(x*x + z*z > 64*64) continue;
            if(!isIceberg(dpnIcebergPillar, dpnIcebergSurface, (float)x, (float)z )) return 0;
        }
    }

    return 1;
}

void printSeed(DoublePerlinNoise* dpnIcebergPillar, DoublePerlinNoise* dpnIcebergSurface, float xOffset, float zOffset)
{
    for(int z = 0; z < 64; z++)
    {
        for(int x = 0; x < 64; x++)
        {
            if(isIceberg(dpnIcebergPillar, dpnIcebergSurface, (float)x*4 + xOffset, (float)z*4 + zOffset )) printf("# ");
            else printf("_ ");
        }
        printf("\n");
    }
}

int main()
{
    //find the biggest iceberg/just find the iceberg noise
    //using the already done NormalNoise(DoublePerlinNoise) thing
    NoiseParameters npIcebergPillar = {
        .name = "minecraft:iceberg_pillar",
        .firstOctave = -6,
        .ampCount = 4,
        .amplitudes = (float[]){1.0, 1.0, 1.0, 1.0},
    };

    NoiseParameters npIcebergSurface = {
        .name = "minecraft:iceberg_surface",
        .firstOctave = -6,
        .ampCount = 3,
        .amplitudes = (float[]){1.0, 1.0, 1.0},
    };

    //make noise constants correct
    md5NoiseCalc(&npIcebergPillar);
    md5NoiseCalc(&npIcebergSurface);

    #pragma omp parallel for
    for(uint64_t i = 0; i < 1000000000; i++)
    {
        DoublePerlinNoise dpnIcebergPillar;
        DoublePerlinNoise dpnIcebergSurface;
        //init noises needed for iceberg map
        initClimateSeed(&dpnIcebergPillar, &npIcebergPillar, i, 8);
        initClimateSeed(&dpnIcebergSurface, &npIcebergSurface, i, 6);

        if(isValidSeed(&dpnIcebergPillar, &dpnIcebergSurface))
        #pragma omp critical
        {
            printSeed(&dpnIcebergPillar, &dpnIcebergSurface, 0.0, 0.0);
            printf("%ld\n\n", i);
        }
    }
}